Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Squarified Treemaps in XAML & C# using Microsoft Longhorn

0.00/5 (No votes)
2 Jun 2004 26  
Data visualisation using squarified treemaps.

Demo application - treemaps.png

Introduction

After that strange title, I'd better kick off with an explanation of what this article is all about.

One of my favourite 'pet' topics is data visualisation and how graphically displaying data you can often see trends, patterns & anomalies and often improve the 'user experience (UX)'.

This article is going to be in three main parts; firstly I'll discuss what Treemaps are, how they can help you interpret data and how they are built. But briefly, they provide a graphical representation of information enabling users to compare items by size and changing attributes, often used to view hierarchical data.

Secondly, digressing slightly off topic, I will discuss why I hope & think Longhorn and XAML will bring about important changes to desktop computing.

Then back to treemaps to show how to create the Treemap application in C# and XAML using the alpha builds of Microsoft Longhorn (codename for the next release of Microsoft Windows) and Whidbey (which will be released as Visual Studio 2005 next year) from the October 2003 Microsoft Professional Developers Conference (PDC).

Because I appreciate most people won't have the PDC bits installed, I have also put together a little video demo for people to download in the style of the Longhorn Concept Videos. Hopefully Microsoft and Carter Maslan will appreciate me wanting to evangelise and not be upset by the similar style.

Note, the video is in no way produced nor endorsed by Microsoft and the codenames used in this article belong to their respective owners.

Download video demo - 3762 Kb

Finally, I'll be taking a look at some other visualisation/interactive techniques I've seen lately that might be quite interesting to you; including commercial packages and ideas for viewing information.

Background

I came across the graphical technique called Treemaps about four years ago on the SmartMoney website. The technique is used there as a way of comparing financial stock information and is called 'Map of the Markets'. It impressed me with how easily it allowed users' to compare the size and the change of different attributes for multiple sectors and companies.

Wanting to understand how they calculated and laid out the different areas, I researched deeper and found academic papers on Human Computer Interaction (HCI), in particular Treemaps. There I came across the work done by Ben Shneiderman of the University of Maryland.

From there specifically the paper "Squarified Treemaps", by Mark Bruls, Kees Huizing, and Jarke J. van Wijk of the Eindhoven University of Technology, Dept. of Mathematics and Computer Science, which is the layout technique I'll be using here.

There are many examples of people using treemaps, including Microsoft Research on Netscan to analyse Usenet posting, showing which groups have the most posts and the change from last month. You can download their Treemap.NET SDK.

The HiveGroup have a product using treemaps for business intelligence data mining.

Squarified Treemaps

These are a type of treemap, but the layout algorithm aims to draw the data with the "best" aspect ratio, ie. trying to keep the area's shape "square" by aiming for a low aspect ratio approaching the value 1.

So let's start with a simple example, imagine we have five different companies. We have data on millions � of sales and the % change from last year.

We could show the data as a table:

Or graphically as a chart:

This allows us to see easily that Company B (the largest sales) had a negative percentage change on sales from last year. Company F is about half the size of Company E and the smallest Sales was Company G but Company H had highest change % from last year.

Drawing that information as a Squarified Treemap gives us a diagram like this:

To explain what we are looking at, we have drawn all the companies in a grid with the size determined by the Sales figure; the colour gives the % change. Hopefully you will agree that it is easy to get a good idea of the companies from a quick glance, and compare the size of sales. Also the bright green colour on Company H makes it stand out as a positive % change, and that Company C, D, J and G are similar in sales size.

 

The technique isn't really that impressive with a small data set, but with more companies you can glance and pick out anomalies really quickly. If we look at a couple of screenshots from the Smartmoney Sector Map we can see negative changes in "Technology Hardware & Equipment" and "Communications Technology" below very easily.

Drilling further into the Software sector on Smartmoney, we can see the dominance (in market capitalisation) of Microsoft.

Did you really know Microsoft was that much bigger (in market capitalisation) than Oracle?

How the layout works?

Now we have seen how the technique shows data, how do we decide on the actual layout of the data?

In the paper "Squarified Treemaps" as listed above, it discusses using a layout technique to try and obtain the best aspect ratio; as mentioned before, that means trying to layout the elements to get the ratio to approach the value 1.

I'm going to use their example again, say we have an area of 6 x 4 and we have seven items of data with sizes of 6, 6, 4, 3, 2, 2 and 1 respectively.

We could split the area vertically:

Or horizontally:

Neither really looks very good, the idea put forward in the Squarified Treemap paper is to try placing the items down differently aiming for the optimum aspect ratio.

 

Step 1 : Start by deciding that because the area we want to fill is wider than the height we'll draw the first element vertically.

bool DrawVertically (single width, single height) { 
    return width > height; 
} 

We calculate the aspect ratio as:

single aspect = Math.Max( width / height, height / width); 

We are placing an element of size 6, given the height is 4 (as we are drawing vertically).

Then width = 4 * ? = 6, so ? = 6/4 = 1.5

Aspect ratio is Max( 4/1.5, 1.5/4)
= 2.66

 

Step 2 : Continue drawing vertically as we didn't have a previous aspect ratio to better. Now we want to draw the first two elements of size 6 and 6.

Placing a total size of 12 (6+6), given the height of 4 means:

Width = 4 * ? = 12, so ? = 12/4 = 3

Aspect ratio is Max( 2/3, 3/2) = 1.5

It is better than previous value so we continue.

 

 

Step 3 : Again continue drawing vertically as the aspect ratio improved, ie. getting closer to 1. Drawing the first three elements in the list of size 6, 6 and 4.

Placing a total size of 16 (6+6+4), given the height of 4 means:

Width = 4 * ? = 16, so ? = 16/4 = 4

Item 1, 2 are size 6 = 4 * 1.5
Item 3 is size 4 = 4 * 1

Aspect ratio is Max( 4/1, 1/4) = 4

Worse, so don't use this layout step.

 

 

Step 4 : Because the aspect ratio was worse (higher than value from step 2 and moving away from the value 1), we backtrack to step 2 and lock that layout in place.

Now we are trying to layout the remaining elements into the area left, a 3 by 4 space. As we are starting again, check if we are going to draw vertically, the answer is no because the area is taller than the width. Let's try to place the element of size 4 again.

Placing the element of size 4, given the width of 3 (as drawing horizontally now) means:

Height = 3 * ? = 4, so ? = 4/3 = 1.333

Aspect ratio is Max( 3/1.333, 1.333/3) = 2.251

First item in new area, so let's continue.

 

 

Step 5 : Continue on, drawing horizontally, elements of size 4 and 3.

Placing a total of size 7 (4+3), given the width of 3 means:

Height = 3 * ? = 7, so ? = 7/3 = 2.333

Item 3 is size 4 = ? * 2.333 = 1.715 width
Item 4 is size 3 = ? * 2.333 = 1.289 width

Aspect ratio is Max( 2.333/1.289, 1.289/2.333) = 1.80993

Better than previous value (closer to 1) so we continue.

 

Step 6 : Continue on drawing horizontally, elements of size of 4, 3 and 2.

Placing a total of size 9, given the width of 3 means:

Height = 3 * ? = 9, so ? = 9/3 = 3

Item 3 is size 4 = ? * 3 = 1.333 width
Item 4 is size 3 = ? * 3 = 1 width
Item 5 is size 2 = ? * 3 = 0.667 width

Aspect ratio is Max ( 3/0.667, 0.667/3) = 4.498

Worse, so we don't use this layout step.

 

Step 7 : Because the aspect ratio was worse (higher than value from step 5 and moving away from the value 1), we backtrack to step 5 and lock that layout in place.

Now we are trying to layout the remaining elements into the area left, a 3 by 1.67 space. As we are starting again, check if we are going to draw vertically, the answer is yes this time, because the area is wider than the height. Let's try to place the element of size 2 again.

Placing the element of size 2, given the height of 1.67 (as drawing vertically again now) means:

Width = 1.67 * ? = 2, so ? = 2/1.67 = 1.198

Aspect ratio is Max( 1.67/1.198, 1.198/1.67) = 1.394

First item in new area, so let's continue.

 

Step 8 : Continue on drawing vertically, elements of size 2 and 2.

Placing a total of size 4, given the height of 1.67 means:

Width = 1.67 * ? = 4, so ? = 4/1.67 = 2.4

Item 5, 6 are size 2 = ? * 1.67 = 0.84 height each

Aspect ratio is Max ( 0.84/2.4, 2.4/0.84) = 2.87

Worse, so we don't use this layout step.

 

Step 9 : Because the aspect ratio was worse (higher than value from step 7 and moving away from the value 1), we backtrack to step 7 and lock that layout in place.

Now we are trying to layout the remaining elements into the area left, a 1.8 by 1.67 space. As we are starting again, check if we are going to draw vertically, the answer is yes again, because the area is wider than the height. Let's try to place the element of size 2 again.

Placing the element of size 2, given the height of 1.67 (as drawing vertically) means:

Width = 1.67 * ? = 2, so ? = 2/1.67 = 1.198

Aspect ratio is Max( 1.67/1.198, 1.198/1.67) = 1.394

First item in new area, so let's continue.

 

Step 10 : Continue drawing vertically, elements of size 2 and 1.

Placing a total of size 3, given the height of 1.67 means:

Width = 1.67 * ? = 3, so ? = 1.8

Item 6 is size 2 = ? * 0.56 = 1.2 width
Item 7 is size 1 = ? * 0.56 = 0.6 width

And as it is the last element we are done.

 

Obviously this example is made easier to understand because the total size of the elements (6+6+4+3+2+2+1 = 24) which is also the total area (6 by 4 = 24). But a different number and total size of elements could have been placed it would have just involved scaling the sizes appropriately.

I hope people have been able to follow that explanation and you can see how recursively we try different layouts, with the end result a much more "square" and better laid out set of elements descending in size.

We'll come back to the actual code and colouring of the change parameter a bit later in this article.

 

Please feel free to skip this next discussion about Longhorn if you are only interested in the squarified treemap code.


Why could Longhorn bring huge changes?

The next release of Microsoft Windows after Windows XP is codenamed Longhorn. A lot of information has been released by Microsoft already, including talking about three main pillars, namely Avalon, WinFS, Indigo and the overall fundamentals; collectively known as WinFX.

I'll let you read the Microsoft Developer Network (MSDN) articles on the Longhorn Developer Center to learn more.

The book Introducing "Longhorn" for Developers by Brent Rector is a good roadmap guide and is all available to read on-line now as well.

Looking at the graphics subsystem, in particular "Avalon" which is described as "providing the foundation for building applications and high fidelity experiences in Longhorn, blending together application UI, documents, and media content, while exploiting the full power of your computer ".

Built on top of this is "Aero" is "the new Windows user experience. Aero consists of guidelines, recommendations, and user experience values that help your applications get the most out of the Microsoft Windows ". You don't need to fully understand these terms but it will probably make things a bit clearer.

I'm only really going to be concerned with Avalon and touch on Aero in this article, because they are at the heart of the Longhorn UX.

A new way of way of defining UI layout in Longhorn is XAML (pronounced 'Zamal'). This new markup language allows you to declaratively to specify a hierarchy of objects with a set of properties and logic. Normally this will be a user interface (UI) for an application and this is what I'm going to use for the Treemap application discussed below.

Why Avalon could be so important

Ok enough, what are these new user interfaces going to be like. Well David Massy, wrote a blog entry that I'd like to quote from:

"Why Longhorn and Avalon?

I don't know if anyone else out there watches the CSI and CSI: Miami shows on television (presumably someone else watches them or they would not continue to make the show), they involve Crime Scene Investigators sifting through evidence to find the bad people responsible for the crime. It may not be the best TV show but my fianc�e and I often enjoy watching it trying to guess who the bad guy is. However the thing that bugs me about that show (and a lot of other TV shows and films) is the way they show computers working, the computers on these shows have slick interfaces that flash up instant results of a query including a driver's license image and other related data, they offer 3D analysis of tire tread matching, shoe print matching, DNA matching etc etc., even the login screen is slick and inviting.

So in Longhorn the technologies in Avalon are going to bring the types of user interfaces we see in these shows within the easy reach of developers. Great!

Well of course the cynical among you are probably saying something like "but I actually don't really want something that looks like what they show on TV" well I'd probably agree with you as the TV shows are always going to show something a little more simplistic than what might be used in the real world simply so that the viewer can easily follow the plot. That's not to say that elements of what is typically seen on TV aren't useful and isn't something we should provide in the next generation of computer solutions. For many people today computers remain too difficult to use and offering a glitch free user experience that guides you through getting a task done with animation helping show the flow of the task will I believe help here."


A recent article in Discover magazine, talks of how My Pictures might work in the future, "If you take 10 consecutive shots of a sunset, the software will recognize that all those pictures were snapped within a matter of minutes and pull them into a single stack. The organizational scheme is logical enough, but what makes the software impressive is the visual appeal of all the images flying across the screen to stack themselves up into an orderly pile. (The effect is not unlike that created by an expert blackjack dealer plying his trade at a table in Vegas.) File management is not normally something that brings a smile to my face, but Wong and Drucker's photo tool had me leaning into the screen."


Or the ExtremeTech review of the WinHEC alpha release of Longhorn, where the task switching "tilted list of windows. You can actually see the contents."

As this screenshot from the Winsupersite showcase shows, imagine Control Panel like this where the elements slide around like the timeline in Picasa mentioned below. Ok maybe not in a corporate environment but it would wow home users and make them feel like it really is the 21st century. As long as there is a balance between functionality and aesthetics I think it will be a step forward.

You only have to look at some of the consumer UIs for the XBox or Windows XP Media Center Edition, in particular the intro video, to see that it really can impress and be functional.

Take a look at Picasa and the timeline view. It shows your pictures on a scrolling timescales with smooth animation.

Many people really like the Apple OS X interface and I would agree that the machines look really nice and the effects do impress passers by. You can try something similar on Windows XP via AquaDock.

But for me, I wanted the taskbar back pretty quickly; read more on OS X vs Windows XP.


So how do we balance the two, well Hillel Cooperman and Tjeerd Hoek Talk Longhorn (Part Two) shows a lot of work, thought and usability testing is going into the UX these days.

At Microsoft Research, they are looking at improving the UI interface continually, the recent article, "Wave Goodbye to the Ordinary User Interface" talks about being "inspired by how computers work in movies. In movies, you never have to login, you never have to type a file name, you never have to remember the URL, or know what a browser is. There's none of these artificial distinctions. Things just happen."

"In GWindows we use two webcams above the monitor. The machine senses when there is something in the space in front of the webcams. It puts up a little hand on the computer display. You can grab onto a window, move it, and let it go. Or you can say 'scroll' and it maps the up and down scrolling motion. So you can combine speech and gesture".

This sort of stuff has been in the research labs for years, will it ever hit the mainstream? Will we start to see displays and interactions like in the film Minority Report?

User eXperience (UX)

As we mentioned, adding a gradient and a fade effect doesn't make a great application, and I think a number of people are concerned that by allowing developers to easily embed video, graphics, rotated animating text and buttons the UI could become an absolute mess. No offence meant to Chris Anderson and Don Box's Lap around Longhorn example! But this is possible today, just think back to the <marquee> <blink> tags in HTML pages and a hundred and one different fonts in a Word document.

It has to be used in a useful and appropriate way. Just as with Java UI you have the "Java Look and Feel Design Guidelines" and on Windows the "Official Guidelines for User Interface Developers and Designer" the fundamentals of "User-Centered Design Principles".


We can start to see Microsoft pushing out guidance in this area with the "Aero User Experience Guidelines: Sampler for PDC 2003"

The aim being a new set of books code-named "The Windows User Experience Cookbooks" which will include guidelines and examples of good Aero user experience design. These books will show you how to:

Design products that look and act like a new Longhorn application.

  • Deliver a great end-to-end user experience.
  • Be a good Windows "citizen".

The link to sampler above compiled for PDC 2003 contains preliminary versions of chapters, discussing the:

It describes different groups of applications, called "Application Archetypes", showing how the UI can share some consistently across similar groups.

For example an on-line travel website, could combine the web-like presentation with rich listview-type controls.


We are going to need guidelines on creating vector graphics and icons similar to Creating Windows XP Icons.

Where it talks about the Windows XP icon style of fun, colour, and energy � and, as there are now 32-bit colour versions of the icons, smooth edges. With each icon being rendered in a vector program and then manipulated in Adobe Photoshop to create a beautiful image.

These guidelines are geared towards designers. So they recommend working with a good graphic designer, especially one with experience in using vector or 3D programs.


Just very quickly touching on WinFS for a moment, if you have Longhorn installed, take a look at the file c:\windows\system32\winfs\schema\contact.xml to see how much thought is going into the schema design on contacts. Even at this early stage it is quite impressive and hopefully will continue to improve.

So what is XAML?

As we have mentioned it can be seen as a declarative markup language for Windows, what makes it special is:

  • One-to-one correspondence with object model.
  • Markup & code are peers in functionality and performance.

This will enable interoperation between UI authoring tools and developer tools and help:

  • Keep code and content separate.
  • Streamline collaboration between designers and developers.


I'm not to going to describe all the different objects, but we'll have a very simple example.

In XAML:

<Button Width="100px" 
  Background="LightBlue">OK
</Button> 

In C#:

Button b1 = new Button();
b1.Content = "OK"
b1.Background = new SolidColorBrush(Colors.LightBlue); 
b1.Width = new Length(100); 

Would give:


One of the first questions is why invent something new? There are already declarative markup languages, even contests comparing them. Isn't SVG (Scalable Vector Graphics) the standard for vector graphics, but as Ian Griffiths points out in the article Introducing the New Avalon Graphics Model, that would lose one of the main points one-to-one correspondence with object model and coherence with the naming conventions of the .NET framework.

There are other markup languages for describing UI and even contests comparing them. One I think will be interesting to watch is Macromedia Flex but it seems like the pricing for the server may be too high.

For a more general introduction to XAML, read the MSDN Article, "A First Look at Writing and Deploying Apps in the Next Generation of Windows".

From the Bitmap world to scalable Vectors

With Avalon most of the UI for the Windows Shell will be drawn as vector graphics. This means they can be scaled without ending up looking blocky, as would happen if done with bitmapped images; much in the same way Adobe Type Manager/TrueType made fonts scalable in Windows.

Paul Thurrott gives a good example in his review where he shows the differences below.

Bitmap image scaled:

This isn't really a vector image but an icon from OS X, but I hope it does give the idea of how a better scaled image should work at different resolutions:

Chris Sells, in his article "A Journey of a Thousand Miles" talks about vector based images for the card images in the new Solitaire game he is writing as part of learning Longhorn.

Again, Introducing the New Avalon Graphics Model by Ian Griffiths talks more about the XAML and vector paths.

So are Winforms a dead technology?

If XAML is the future, should people invest time learning about Winforms today? Well really the question is, given that Longhorn is looking like 2006 at the earliest can you afford not to release an application for anyone to use till then?

The answer is probably no, but as David Massy from Microsoft points out in Why wait for Avalon?:

"Should you wait for Avalon? Probably not but you should be thinking about all the capabilities that Longhorn is going to bring to developers and how this might enable your applications to offer greater capabilities and significantly improved ease of use.
I'd strongly encourage all developers and architects to watch closely the progress we make on Longhorn so that you are ready and prepared when it arrives. Of course don't forget the importance of managed code in Longhorn as well. Managed code and the .NET framework is central to the future of Windows.

So I'd say don't wait, embrace managed code and the .NET framework today but watch Longhorn closely for what it will provide."

A similar posting by Robert Scoble, WinForms is dead misconceptions are misplaced, had a lot of people discussing the situation.


I answered a similar question on Zohar Melamed's blog on .NET functionality being deprecated at a quick rate with a similar answer.


Back to the Coding Part!

Pre-requisites - Installing the PDC bits

I'm afraid that most people won't have the PDC bits, but if you or your company has an MSDN Universal subscription you can download the alpha 4051 Longhorn build.

Also guessing if people went to the PDC then they will have installed and played around with the bits over the last few months. But maybe like me, before writing this article, you have a full-time job to do and only get to try things out at home as and when you can so you haven't had much exposure.

It is all good reading articles and having an idea of how technologies work, but you really don't begin to learn until you really try and write an application; much like learning to drive after passing your driving test or how I felt moving from COM world to .NET a few years ago.

You can see some screenshots of the Longhorn PDC 4051 build at Winsupersite.

Approach

My approach was to work on the C# implementation of the Treemap calculation code separately, get that working and then look at how to combine and generate the XAML code.

By taking small steps, I could more easily debug and change coding direction as I discovered more, especially which XAML layout panels to use where.

I didn't have a spare PC to install and test the alpha bits, so instead I used VMware Workstation 4.0.5 to create a virtual PC using the 30 day evaluation version available. I'm sure it would work fine under Microsoft Virtual PC 2004 if you have that instead.

Specification wise you should really give the virtual session 512Mb of RAM and 8Gb of disk space if you intend to install all the development tools, software development kit (SDK) and documentation.

Make sure you follow the release notes, because the order of installation on Longhorn is very important.

Also download and install the XAML IntelliSense Patch for PDC Visual Studio .NET "Whidbey" to improve the IntelliSense editing of XAML files.

Designing the layout XAML code

Working out how to draw the rectangles and layout in XAML was a process of trial and error. I had a reasonable idea of the different types of layout shapes and panels, but exactly which elements would work I wasn't sure, so had to just play around with them.


The Rectangle seemed a pretty good fit,

<Rectangle Fill="red" StrokeThickness="2" Stroke="darkgray" 
 Height="100" Width="100" /> 

For absolute positioning, could change to:

<Rectangle Canvas.Top="200" Canvas.Left="200" Fill="red" /> 

Looking good so far, next the mouseover animation � which I wanted the gray border to change to white. So reading Create a Rollover Effect Using Events and Animating Property Triggers I started in that direction.

Which would mean I could declaratively define the change centrally in a style, in MyApp.xaml:

<Style def:Name="treemapRect"> 
   <Rectangle StrokeThickness="2" Stroke="darkgray" />
   <Style.VisualTriggers> 
      <PropertyTrigger Property="IsMouseOver" Value="True"> 
         <Set PropertyPath="Stroke" Value="white" /> 
         <Set PropertyPath="Cursor" Value="Hand" /> 
      </PropertyTrigger> 
   </Style.VisualTriggers> 
</Style>

Note, need to be careful editing XAML styles in Visual Studio, as it often incorrectly closes tags where it shouldn't, just keep an eye out if you are typing away.

The way to assign a style to an object is:

<Rectangle Style="{treemapRect}"> 

Which seemed a bit strange to me, there are a lot of similarities to HTML/CSS but then a lot of differences too. We'll see how this pans out in the future.

Unfortunately, this didn't work as expected, although it might be my misunderstanding. The Stroke colour change was ignored, even though the Cursor changed.

However setting the value in actual C# code from the MouseEnter and MouseLeave events did update the border colour.

<Rectangle MouseEnter="HighlightRect" MouseLeave="HighlightRect"> 

private void HighlightRect (object sender, 
                            MSAvalon.Windows.Input.MouseEventArgs e) 
{ 
   MSAvalon.Windows.Shapes.Rectangle r = 
                (MSAvalon.Windows.Shapes.Rectangle)sender; 
   MSAvalon.Windows.Media.SolidColorBrush brush = 
                (MSAvalon.Windows.Media.SolidColorBrush) r.Stroke; 

   if ( brush.Color == Colors.White ) 
      r.Stroke = new SolidColorBrush(Colors.DarkGray); 
   else 
      r.Stroke = new SolidColorBrush(Colors.White); 
} 

I did try to add the MouseEnter and MouseLeave events to the style, but got the error "Events not support in style declarations". I didn't look any further into this, but guessing will be possible to add CSS behaviour type code maybe using delegates?

Note, because the XAML and C# code are partial classes, you no longer have to declare markup objects in C# as you currently do with ASP.NET. This is true for ASP.NET in the Whidbey release; a big improvement over ASP.NET 1.x.


Another problem, which might be a bug in the Longhorn PDC build or not, was trying to change the StrokeThickness value caused the layout to enter an infinite loop causing the error:



As you might have realised by now, development on Longhorn is a journey of discovery as expected of an alpha build. One little aside, is that because of the stronger typing of XAML than HTML you cannot quickly comment out markup. Often in HTML I'll just change <� style="font-family: Verdana;"> to <� xstyle="font-family: Verdana;">. Meaning that xstyle is not a valid attribute and thus will be ignored, but in XAML the code wouldn't compile. You can comment out tags with <!-- --> but would be nice to be able to remove an attribute quickly when testing without having to cut-n-paste it into notepad for safe keeping.

Because I wanted text inside the rectangle, I thought I'd try this:

<Rectangle Fill="red" Width="100" Height="100"> 
   <Text>Hello there</Text> 
</Rectangle> 

But this didn't work, the text wasn't visible and the old Windows idea of z-order didn't seem to the right place to look.

So I tried:

<Rectangle Fill="red" Stroke="darkgray" StrokeThickness="2" 
   Cursor="Hand" Width="100" Height="100" 
      Canvas.Left="0" Canvas.Top="0" MouseEnter="HighlightRect" 
      MouseLeave="HighlightRect" /> 
<Text Width="100" Height="100" Canvas.Left="0" 
   Canvas.Top="0">Hello there</Text> 

Which meant coding the Left and Top positions twice, but it did draw the text on top of the Rectangle. Unfortunately now the MouseEnter event didn't fire as the Text control was covering the Rectangle!


Then I thought actually why bother with a Rectangle and not just set the background colour of the Text control. But this isn't a property of the Text control (it might be for the text panel), so I instead wrapped a Border control around the Text control.

Note the change from Stroke and StrokeThickness to BorderBrush and BorderThickness, also why Fill and Background on different controls? Also ID not following the .NET framework guidelines of calling it Id? Sure these things will pan out in time before it is released properly.

<Border Canvas.Left="100" Canvas.Top="0" Width="100" Height="100" 
   BorderBrush="darkgray" BorderThickness="2" Background="red" Cursor="Hand"> 
   <Text Foreground="white" TextWrap="Wrap" TextTrimming="CharacterEllipsis" 
      VerticalAlignment="Center" HorizontalAlignment="Center" 
      Width="98%" Height="98%" MouseEnter="HightLightText" 
      MouseLeave="HighLightText">My text inside the Border</Text> 
</Border> 

Looking good, think we have the basis for drawing the Treemap rectangles. Because we will be creating them in code I'll need to translate the XAML to C#.

If you debug the application and have a look at the obj/Debug/Windows1.g.cs which is the generated C# from the XAML markup you can see what is actually compiled. It is yuck, but it does give an idea of what is actually called.

Armed with that, the C# code would be:

private void WindowsLoaded (object sender, EventArgs e) 
{ 
   MSAvalon.Windows.Controls.Border b = new MSAvalon.Windows.Controls.Border(); 
   MSAvalon.Windows.Controls.Text t = new MSAvalon.Windows.Controls.Text(); 
  
   // Could use overload on Length to assume pixels 

   Canvas.SetLeft (b, new Length(100, UnitType.Pixel)); 
   Canvas.SetTop (b, new Length(100, UnitType.Pixel)); 
   b.Width = new Length(100, UnitType.Pixel); 
   b.Height = new Length(100, UnitType.Pixel);
   b.BorderBrush = new SolidColorBrush(Colors.DarkGray); 
   b.BorderThickness = new Thickness(new Length(2, UnitType.Pixel)); 
   b.Background = new SolidColorBrush(Colors.Red); 
   b.Cursor = MSAvalon.Windows.Input.Cursor.Hand(); 
  
   t.Foreground = new SolidColorBrush(Colors.White); 
   t.TextWrap = TextWrap.Wrap; 
   t.TextTrimming = MSAvalon.Windows.TextTrimming.CharacterEllipsis; 
   t.VerticalAlignment = MSAvalon.Windows.Media.VerticalAlignment.Center; 
   t.HorizontalAlignment = MSAvalon.Windows.HorizontalAlignment.Center; 
   t.Width = new Length(98, UnitType.Percent); 
   t.Height = new Length(98, UnitType.Percent); 
    
   ((MSAvalon.Windows.Serialization.IAddChild)(t)).AddText("My text 
                                                      inside the Border"); 
    
   t.MouseEnter += new MSAvalon.Windows.Input.MouseEventHandler 
                                                   (this.Highlight); 
   t.MouseLeave += new MSAvalon.Windows.Input.MouseEventHandler 
                                                   (this.Highlight); 
   ((MSAvalon.Windows.Serialization.IAddChild)(b)).AddChild(t); 
  
   oCanvas.Children.Add(b); 
} 

Give me declarative markup any day of the week, and why is it VerticalAlignment in MSAvalon.Windows.Media but HorizontalAlignment in MSAvalon.Windows namespace?

Also I would have liked to look at using some of the advanced databinding control features in XAML.

When writing the code and playing with XAML I did keep asking myself, is it "better" because it's new and fun or is it really an improvement? Guess one way to look at it is how difficult would a automatically reflowing document panel with a floating rounded gradient filled vector scalable transparent rectangle be to draw under GDI+ code? I'll leave you reading Charles Petzold books for a while then�

<Canvas ID="oInfoCanvas" Width="160" Height="58" Opacity="0"> 
   <Rectangle ID="oInfoRect" RadiusX="4" RadiusY="4" Height="100%" 
       Width="100%" Stroke="#1978B1" StrokeThickness="2" 
       Fill="VerticalGradient #FFC6EBFF #DDFFFFFF" /> 
   <TextPanel Canvas.Left="10" Canvas.Top="6" FontSize="10" 
       FontWeight="Bold"ID="oInfoName"></TextPanel> 
   <TextPanel Canvas.Left="10" Canvas.Top="24" FontSize="10" 
       ID="oInfoSize"></TextPanel> 
   <TextPanel Canvas.Left="10" Canvas.Top="36" FontSize="10" 
       ID="oInfoChange"></TextPanel> 
</Canvas> 

Squarified Treemap Calculation Code

The actual code for calculating the sizes and colour of each element isn't really to complex. It is just like following the steps in the example above.

I used DataSets for passing the actual data to draw to the Treemap class and for the return calculated values for the items, ie. size, position and colour.

public class Treemap
{
   private int width;
   private int height;

   private double changeLimit = 4; // Should really calculate this

                                   // automatically from the given dataset


   ... 

   public Treemap()
   {
      // Constructor

      returnDs = new DataSet();

      DataTable dt = new DataTable();
      dt.Columns.Add("id", typeof(string));
      dt.Columns.Add("name", typeof(string));
      dt.Columns.Add("size", typeof(Single));
      dt.Columns.Add("change", typeof(Single));
      dt.Columns.Add("x", typeof(Single));
      dt.Columns.Add("y", typeof(Single));
      
      ...

      returnDs.Tables.Add(dt);
   }

   public DataSet GetData()
   {
      // Remove temporary calculation columns

      returnDs.Tables[0].Columns.Remove("sizeTmp");
      returnDs.Tables[0].Columns.Remove("changeTmp");
      returnDs.Tables[0].Columns.Remove("widthTmp");
      returnDs.Tables[0].Columns.Remove("heightTmp");
      return returnDs;
   }

The CalcMap function loops around the data and then calculates the scaling and change colours for each item.

public void CalcMap()
{
   CopyValues(); // Copy values from original DataSet to return DataSet

   
   tmp_dWidth = width;
   tmp_dHeight = height;

   double valueScale = 0;
   double changeTotal = 0;
   double dataTotal = 0;

   DataTable dt = returnDs.Tables[0];

   for (int n=0; n < dt.Rows.Count; n++)
   {
      dataTotal += (Single)dt.Rows[n]["sizeTmp"];
   }

   // Scale and set colour change value

   valueScale = ((width * height) / dataTotal) / 100;

   for (int n=0; n < dt.Rows.Count; n++)
   {
      changeTotal += (Single)dt.Rows[n]["change"];
      dt.Rows[n]["sizeTmp"] = valueScale * (Single)dt.Rows[n]["sizeTmp"];
      dt.Rows[n]["changeTmp"] = (255 / changeLimit) * 
                                         (Single)dt.Rows[n]["changeTmp"];

      // Reset if we are over colour range

      if ((Single)dt.Rows[n]["changeTmp"] > 255)
         dt.Rows[n]["changeTmp"] = 255;
      else if ((Single)dt.Rows[n]["changeTmp"] < -255)
         dt.Rows[n]["changeTmp"] = -255;
      
      // Set the green or red change colour value

      if ((Single)dt.Rows[n]["changeTmp"] >= 0)
      {
         dt.Rows[n]["r"] = 0;
         dt.Rows[n]["g"] = (int)(Single)dt.Rows[n]["changeTmp"];
         dt.Rows[n]["b"] = 0;
         dt.Rows[n]["htmlColour"] = ColorTranslator.ToHtml(
                                  Color.FromArgb(0, 
                                  (int)(Single)dt.Rows[n]["changeTmp"], 0));
      }
      else
      {
         dt.Rows[n]["r"] = (int)Math.Abs((Single)dt.Rows[n]["changeTmp"]);
         dt.Rows[n]["g"] = 0;
         dt.Rows[n]["b"] = 0;
         dt.Rows[n]["htmlColour"] = ColorTranslator.ToHtml(
                                  Color.FromArgb(
                                (int)Math.Abs((Single)dt.Rows[n]["changeTmp"]),
                                  0, 0));
      }
   }

This next piece of code should but recursive but I use a simple goto statement as a bit of a hack instead. Decide if we are going to draw vertically or horizontally based on whether the area to draw has a width greater than the height.

Then try and draw the current elements defined by start to end range. The Try function attempts to place the items and returns the aspect ratio for the last placed item.

If this aspect ratio is worse than the previous ratio, then we Lock the previous layout positions, set the new remaining area to layout in and start over again.

   int start = 0;
   int end = 0;

   bool vert;

   Single aspectCurr = 999;
   Single aspectLast;
   
   vert = DrawVert(tmp_dWidth, tmp_dHeight);

startover:

   while (end != dt.Rows.Count)
   {
      aspectLast = Try(start, end, vert);

      // Is aspect ratio worse than previous ratio?

      if ((aspectLast > aspectCurr) || (aspectLast < 1))
      {
         Single currX = 0;
         Single currY = 0;

         // Lock the previous items in place

         for (int n = start; n < end; n++)
         {
            dt.Rows[n]["x"] = offsetX + currX;
            dt.Rows[n]["y"] = offsetY + currY;
            
            if (vert)
               currY += (Single)dt.Rows[n]["height"];
            else
               currX += (Single)dt.Rows[n]["width"];
         }

         if (vert)
            offsetX += (Single)dt.Rows[start]["width"];
         else
            offsetY += (Single)dt.Rows[start]["height"];
         
         tmp_dWidth = width - offsetX;
         tmp_dHeight = height - offsetY;

         vert = DrawVert(tmp_dWidth, tmp_dHeight);
         start = end;
         end = start;
         aspectCurr = 999;

         goto startover;
      }
      else
      {
         // Store newly calculate sizes

         for (int n = start; n <= end; n++)
         {
            dt.Rows[n]["width"] = dt.Rows[n]["widthTmp"];
            dt.Rows[n]["height"] = dt.Rows[n]["HeightTmp"];
         }
         aspectCurr = aspectLast;
      }

      // try to draw another item

      end++;
   }

   // Set each item in the positions in the remaining area

   Single currX1 = 0;
   Single currY1 = 0;

   for (int n = start; n < end; n++)
   {
      dt.Rows[n]["x"] = offsetX + currX1;
      dt.Rows[n]["y"] = offsetY + currY1;

      if (vert)
         currY1 += (Single)dt.Rows[n]["height"];
      else
         currX1 += (Single)dt.Rows[n]["width"];
   }
}
The Try function tests setting the total item sizes in the available space and return the aspect ratio of the last item we place.
private Single Try(int start, int end, bool vert)
{
   Single total = 0; 
   Single aspect = 0;
   Single localWidth;
   Single localHeight;

   for (int n = start; n <= end; n++)
   {
      total += (Single)returnDs.Tables[0].Rows[n]["sizeTmp"];
   }

   // Scale as needed for the width or height

   if (vert)
   {
      localWidth = total / tmp_dHeight * 100;
      localHeight = tmp_dHeight;
   }
   else
   {
      localHeight = total / tmp_dWidth * 100;
      localWidth = tmp_dWidth;
   }

   for (int n=start; n <= end; n++)
   {
      if (vert)
      {
         returnDs.Tables[0].Rows[n]["widthTmp"] = localWidth;
         returnDs.Tables[0].Rows[n]["heightTmp"] = (Single)(localHeight * 
                 ((Single)returnDs.Tables[0].Rows[n]["sizeTmp"] / total));
      }
      else
      {
         returnDs.Tables[0].Rows[n]["widthTmp"] = (Single)(localWidth * 
                 ((Single)returnDs.Tables[0].Rows[n]["sizeTmp"] / total));
         returnDs.Tables[0].Rows[n]["heightTmp"] = localHeight;
      }

      aspect = Math.Max((Single)returnDs.Tables[0].Rows[n]["heightTmp"] / 
                  (Single)returnDs.Tables[0].Rows[n]["widthTmp"],
                        (Single)returnDs.Tables[0].Rows[n]["widthTmp"] / 
                  (Single)returnDs.Tables[0].Rows[n]["heightTmp"]);
   }

   return aspect;
}

private bool DrawVert(Single width, Single height)
{
   return width > height;
}

Using the Code

To actually use the Treemap.cs C# code isn't too bad.

Create an instance of the class, set the width and height, assign a DataSet with columns id, name, size and change to the DataSource member. Call CalcMap to calculate the layout and then GetData to retrieve a DataSet with the original columns and additional x, y, width, height, htmlcolour, r, g, and b columns.

Then iterate around the return DataSet drawing items using the x, y, width and height values.

Treemap.Treemap map = new Treemap.Treemap();

map.Width = (int)oMainCanvas.Width.Value;
map.Height = (int)oMainCanvas.Height.Value;

map.DataSource = LoadData();

map.CalcMap();
ds = map.GetData();

for (int n = 0; n < ds.Tables[0].Rows.Count; n++)
{
   MSAvalon.Windows.Controls.Border b = new MSAvalon.Windows.Controls.Border();

   Canvas.SetLeft(b, new Length(
          Double.Parse(ds.Tables[0].Rows[n]["x"].ToString()), 
UnitType.Pixel)); Canvas.SetTop(b, new Length( Double.Parse(ds.Tables[0].Rows[n]["y"].ToString()),
UnitType.Pixel)); b.Width = new Length( Double.Parse(ds.Tables[0].Rows[n]["width"].ToString()),
UnitType.Pixel); b.Height = new Length( Double.Parse(ds.Tables[0].Rows[n]["height"].ToString()),
UnitType.Pixel); ... }

Must apologise for the quality and naming of the code, I really should have reworked and refactored it a lot but once a had it working I didn't feel much like altering in the VMware session as it wasn't the greatest of setups to debug. Remember this is only meant as a demo, so don't judge me on the design please!

Also wished I hadn't used DataSets as Data Transfer Objects between the view and controller, I thought I'd try it for a change but after all the casting and debugging nightmares (even with data visualisers) I'll stick using proper classes.

Sample data and XPath

The sample industries, sectors and company information I use in the demo application I download as .csv information from the Yahoo Finance industry browser website.

I then wrote a quick little Excel VBA macro to export that data as a string which happened to be XML; the schema I just made up.

<?xml version="1.0" encoding="utf-8" ?> 
<Industries Date="8-May-2004" Source="Yahoo Finance" 
   Size="Market Cap (Billions)" Change="1 Day Price Change (%)"> 
 <Industry Id="I1" Name="Services" Size="4393.54" Change="-1.864"> 
  <Sector Id="S1" Name="Communications Services" Size="1640.2" Change="-1.8" /> 
  <Sector Id="S2" Name="Broadcasting &amp; Cable TV" Size="497" Change="-1.22"/> 
  <Sector Id="S3" Name="Retail (Department &amp; Discount)" Size="357.4" 
          Change="-1.35" /> 
  <Sector Id="S4" Name="Real Estate Operations" Size="242.3" Change="-3.4" /> 
  <Sector Id="S5" Name="Printing &amp; Publishing" Size="216.1" Change="-0.82"/> 
  <Sector Id="S6" Name="Retail (Specialty)" Size="208.8" Change="-2.36" /> 
  <Sector Id="S7" Name="Business Services" Size="195.8" Change="-0.4" /> 
  <Sector Id="S8" Name="Retail (Grocery)" Size="162.8" Change="-1.42" /> 
  <Sector Id="S9" Name="Retail (Home Improvement)" Size="120.4" Change="-3.59"/> 
  ... 

This means I can use XPathNavigator to select which set I want to display using simple XPath expressions such as:

/*/* to get all the industries. 
/*/*[@Id='I1']/* to get all the sectors for the I1 industry 
/*/*[@Id='I3']/*[@Id='S1']/* to get all the companies in a sector, industry 

And load the data with this:

XPathDocument doc = new XPathDocument(@"c:\YahooData.xml"); 
  
// Create an XPathNavigator 

XPathNavigator nav = doc.CreateNavigator(); 
  
// Create a node interator to select nodes and move through them (read-only) 

XPathNodeIterator Iterator = nav.Select(currXPath); 
  
while (Iterator.MoveNext()) 
{ 
   dr = dt.NewRow(); 
   dr["id"] = Iterator.Current.GetAttribute("Id", nav.NamespaceURI); 
   dr["name"] = Iterator.Current.GetAttribute("Name", nav.NamespaceURI); 
   dr["size"] = Iterator.Current.GetAttribute("Size", nav.NamespaceURI); 
   dr["change"] = Iterator.Current.GetAttribute("Change", nav.NamespaceURI); 
   dt.Rows.Add(dr); 
  
   textOverview.TextRange.Text = Iterator.Current.Name + " Overview"; 
} 

You could easily replace my XML file with one of your own if you wanted.

Designing the Layout of the Application

Please don't take my demo application as a good example of UI design and what to expect from Longhorn. It was my first attempt at using XAML for forms design and it was quite difficult starting off with no prior knowledge.

It will be interesting to see what the final design-time tools are like for editing XAML.

Ideally they will be a cross between Visual Studio & Macromedia Dreamweaver, Fireworks and Flash with a bit of discreet 3ds max or Alias Maya for the 3D support. All of these tools you can get evaluation versions of to play with, and indeed I did to help with this article.

Given the nature of XAML as a well-formed XML file, it should be easily 'tool-able' and hopefully might support wizards to help optimise in-line markup out to centralised styles.

Squarified Treemaps Concept Video

As mentioned at the start, I wanted to allow people who don't have the Longhorn PDC build installed to see the application working.

I followed the style of the Microsoft Longhorn Concept Videos, which are a must watch if people haven't downloaded them before.

So recorded myself clicking through the application as an .avi file and then used Windows Movie Maker 2 to add some effects and transitions before producing it as a .wmv file; You'll need Microsoft Windows Media Player 9 to play the clip.

I also mocked up how a zooming effect could work if I used some of the XAML animations and transitions using Flash, so a little bit of cheating there.

Download video demo - 3762 Kb Hope you enjoy watching it!

Example Application

You can start the application XAMLTreemaps.exe from the bin\debug directory and making sure the file YahooData.xml is in C:\.

Once loaded click the 'Load Data' button on the right-hand side of the window.

Then notice as you move the cursor over the different areas you gets the additional metadata on the element in the floating window. Click on required Industry to drill into the data down to the sector level.

I've only added data for the 'Software and Programming' sector, so if you click on that it will show you the companies under that sector. Otherwise it will zoom back out to the top level again.

I should have used the navigation features of the XAML window style but it was enough work to get to this stage.

Also I took the data on what was a pretty bad day for the financial markets as most of the sectors/companies price changes were negative. But it is should still give you a good example of how at a glance you can tell switch sectors and stocks are performing positively or negatively.

If you resize the window you have to click Load Data again as I didn't find a way to tie-up the size changed event to the panel.


There are lots of ways to improve the application, such as better handling of names when they don't fit completely, automatically deciding the best range to use as the colour scale. But this is only meant as demo to help you understand the concepts.


Visualisation & Interactive Techniques

Now, as promised, a quick look and mention of a few visualisation and interactive techniques I've seen of late.

Note, I'm not associated with any of these products or companies but list them because I think they are interesting.

At the desktop level, Microsoft Research has some screenshots and a video clip of something they called the Task Gallery.

A research test project from 1999, they used it so learn how different metaphors, interaction techniques and underlying technological infrastructures work for application redirection. We won't see this coming in a future version of Windows but elements of the multiple desktops and categorisation are strong concepts.

There are more research projects at the Microsoft Visualization and Interaction for Business and Entertainment (VIBE) team's page. They describe the team's mission as to design elegant visualization and interaction techniques that span the full spectrum of devices and displays. Patrick Baudisch has a drag and drop enhancement idea among others in Flash you can try.

 

From Sun, Project Looking Glass also aims to evolve the 2D desktops of today.

"What if windows were translucent so that you could see the multiple windows you're working on at the same time? What if you could tack a note to yourself right on the Web page you're viewing? What if your CD or movie database became a 3D jukebox, where titles were joined with images to make finding what you want easier than ever?"

There are more screenshots and an impressive video demo available, definitely one to watch.

 

Another desktop idea is SphereXP, a 3D desktop replacement for Microsoft Windows XP. It's still in the early stages; check out the video clips and try it yourself.


If you watch this NBC video clip interview with Microsoft Research they talk about digital photography (it is a minute or so in). On how to find and organize pictures using a new in development media browser that lets you search, and arrange photos and video clips by date, by indoors or outdoors - by almost any kind of criteria you choose. Passing the mouse over the pictures brings up a large thumbnail. Get everything organized, then create folders and drag and drop the photos and clips where you want them.


Looking now at more simple graphical elements you could incorporate into an application.

Chris Sells talked about Edward Tufte's work on visualising information, "it's my belief that the big deal with Avalon is that it gives us much more powerful tools to deal with data visualization and manipulation".

One example being Sparklines, which Sean Gerety pointed out, where you can enhance displaying data like this:

You could just show the most recent figure:

Or a small rolling timeseries chart, with the expected limits shown in grey, along with other measurements to allow easy comparisons and readings.

A little strange tale, the day after I saw this, I was at work talking to one of the analytics teams and noticed they had one of Edward Tufte's books. After chatting for a while I mentioned sparklines and it turned out they had just implemented them on a website for comparing bond curves.

 

How about this by Ben Fry for a more satisfying way to fill in an address combobox, where as you type the zip code it highlights or zooms into the area. Tip, press 'z' and try it will the zoom on too.


There are a number of products from a company called Inxight, formed as a spin off from Xerox PARC they describe their business focus as "information discovery from unstructured data sources".

One such product is Inxight TableLens, "which provides graphical displays of tabular data that represent a new way to explore datasets - even those that are too large to view and comprehend in table or XY plot form. By creating TableLens objects, users can interact with their data to find patterns and trends for further exploration. Viewing a graphical representation of over 100 columns and 65,000 rows of data - all on the same screen - makes data trends and correlations jump out."

Follow the tour which explains how you can view, sort, group, zoom-in on data. Then try using the interactive demos to look at the top 100 movies or flight delay information, it's pretty easy to see answers to questions that might normally take a while to analyse.

They used to have a standalone desktop version called Inxight Eureka that you could use for view .csv, .xls etc. files with, but sadly that has been discontinued.

Also from Inxight is TimeWall, "while typical time tools are static, inflexible, and ill-suited for displays of large quantities of information, Inxight TimeWall displays time on a living three-dimensional 'wall'. It empowers analysts, decisionmakers, and others to make faster, more informed decisions by placing relevant information at their fingertips."

It makes finding the document you wrote last week easier and is quite similar to the Journal functionality in Microsoft Outlook.

But it goes much further when combined with multiple data sources you can see patterns of across dates or events.


NetMap by NetMap Analytics is an interesting application. It looks very clever, but unfortunately they don't have any interactive demos just this six degress of Kevin Bacon walkthrough.

The idea is for example that you have information on people, insurance claims, addresses, phone numbers, bank accounts, etc. You can link together these relationships and look for patterns, even if they are a few separations apart, zooming and mining deeper.

There is a good PDF document on their website which explains the idea more and how it can be used in investigations. The software was been used by the Australian police to narrow in on the serial backpacker murder.

A similar product called Daisy by Daisy Analysis works on a similar principle. Connecting relationships together and looking for strong patterns.

You can download a trial version and play around with some of the example dataset they provide.

In an early alpha Longhorn screenshot from Winsupersite the contacts are shown in a carousel view. Maybe we'll see something like this leveraging the WinFS metadata to show relationships graphically?


An interesting use of a fisheye technique for viewing data is Datelens. This calendar application for small handheld devices such as PDA uses a fisheye representation of dates coupled with compact overviews. Users control the visible time period, this enables them to see overviews, easily navigate the calendar structure, and discover patterns and outliers.

I've not used it myself to view calendar but the zooming fisheye technique is also used in the Longhorn concept video, Commercial Real Estate.

IBM's Collaborative User Experience research group are doing some interesting work on History flow, in particular changes to Wiki entries.


Finally, a little off topic but still interesting, is how the London underground tube map was redesigned graphically by Harry Beck to better display information but not actually be accurate geographically. The website, A History of the London Tube Maps, has pictures and explanation of how the map has changed over the years.

Note, these maps are copyright Transport for London, which is why I've used small images and linked them for you to view properly.

From this in 1932:

Copyright Transport for London

To the modern circuit schematic representation of today:

Copyright Transport for London

Transport for London has a flash movie called the Real Underground which shows how the lines reposition between the two styles of map.

Round-up

So let's finish up this article now with a brief wrap-up of future possible enhancements to the Squarified Treemap code and some references to further reading.

Further Enhancements

Looking mainly at what changes you might make to the Squarified Treemap implementation shown in this article:

  • Not having to recalculate layout sizing or do more efficiently.
  • Cleaner code, especially refactor the goto statement and replace with recursive method.
  • Remove use of DataSet as transfer data object to remove some of the casting of types.
  • Add better colour range for the change variable, instead of having the developer have to set a +/- value, decide on the spread and optimal range automatically.
  • Support missing values in datasets so they don't skew calculations.
  • Show lower hierarchy information as treemaps inside the treemap when zoomed out.
  • Improve the decoupling of calculate layout code to rendering, so you could plug in an HTML, GDI+ render easier.
  • Package the code for better reuse.
  • Give the application an import ability, so users can load their own data.
  • Use animations to show the zooming when drilling into the data.
  • XAML speed improvements and optimisations.
  • Use the navigation buttons from the Longhorn windows style to move back and forward.
  • Convert into a sidebar tile for Longhotn.
  • Provide code for rendering to HTML, GIF + imagemap, etc.

Points of Interest

I bought an additional monitor a few months ago and it really does help when you are developing and reading documentation, combine it with UltraMon and it does increase productivity.

Also I tried to use some of the automated refactoring support in Whidbey to 'extract method' on some of the code but it didn't seem to work on my project. Apologies as there are a lot of bad 'code smells' that could do with refactoring out if this demo.

If you haven't read Martin Fowler's book on Refactoring I can definitely recommend it.

Partial classes are a big improvement for XAML/C# coding, not having to add protected member variables for each control removes this painful burden from the developer.

It would be relatively easier to take the C# Treemap.cs class and add support for rendering the map inside a Winforms application or Java applet or an absolutely positioned set of DIV tags in HTML.

References

And for future reading on Information Visualisation, this book Information Visualization.

Conclusion

I hope this article has been of interest to you, again apologies if it was too long. When reading blogs and new information everyday there just seemed to be more to add all the time.

Now maybe you'll want to try some visualisation techniques in your next project to help either yourself or your users' make better decisions.


Please note, the Squarified Treemap layout idea was not devised by myself but by Mark Bruls, Kees Huizing, and Jarke J. van Wijk of the Eindhoven University of Technology, Dept. of Mathematics and Computer Science in their research paper. In this article I just converted their idea into C# code and used XAML as the display render language, again this could easily be adapted to be drawn in GDI or HTML.

Thanks to Stephen Turner of Microsoft UK MSDN for the Avalon presentation a few weeks ago, as I'd been working with XAML for a while it was good to hear the real explanation of what things like RetainedVisual are.


When writing the code and putting together this article I used the Longhorn SDK on the MSDN website, but just last week they updated it because of the new build that was released at the WinHEC conference. One of the major changes was the namespace MSAvalon to System.Windows, so just be aware if you try to port the code from the PDC build.

So XAML is an another new technology to learn and it is still quite a few years away but if you are a Windows developer then I think it is a positive step towards combining the ease of web development with the richness of the Windows platform.


Microsoft has a lot of Longhorn evangelists wanting to get people excited about Longhorn and its technologies, and keeping that momentum going when it is still quite far off will be a challenge, I hope I've helped a little here.

 

Thanks again for reading and let me know if you have any feedback.

History

14th May 2004 � Initial release to the Code Project.
3rd June 2004 - Minor hyperlink formatting changes and hyperlink to video demo on image.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here