Sunday, October 18, 2009

Working with the 1.5 code base : part 5

Away with the dreaded WPF, and back to good old CCNet coding ;-)
This part will cover another updated part of the code : communication. In 1.5 Craig introduced messaging, Changing to Messages. As always Craigs blog is very informative in what and why he changes. I'll try to give a more hands-on example, so others can see more details and some code.
The problem : In CCNet 1.4.3 I exposed the breakers of a build to cctray and the dashboard. Cradiator also uses this information. Now in CCNet 1.5 Craig, yes he again, exposed also the breaking tasks, which is good. But this introduced a problem : the xml feed Cradiator uses, only exposes the last message! So this means that we show the breaker, OR the breaking tasks. (also the dashboard has this problem for the moment)
The solution is simple : expose all messages :-) This is covered in Jira Issue 1718
Anyway, this kind of information is stored in the messages arraylist on the project being integrated. When a build is ok, we clear this list, when a build is bad, we look at the modifications, and extract the user names. The same goes for the tasks that failed. All this information is just a message in this arraylist. This also is a problem on its own. A message is just a text : John Wayne Broke the build. You can not see what kind of information it is, only by parsing the text :-(

Fixing the issue :
Step 1 : add a type for each message
Currently I have these 4 types in an enum
  • NotDefined
  • Breakers
  • Fixer
  • FailingTasks
This is just adding a property with the enum to the message class

/// <summary>
/// The type of message
/// </summary>
[XmlText]
public MessageKind Kind
{
get { return messageKind; }
set { messageKind = value; }
}
Step 2 : adjusting the communication
We need to update the MessageRequest to have this new property also

/// <summary>
/// The kind of message
/// </summary>
[XmlElement("kind")]
public Message.MessageKind Kind
{
get { return kind; }
set { kind = value; }
}
Everywhere where we go from a MessageRequest to a Message we need to pass this new property value. This is in 1 place : CruiseServer.cs in public virtual Response SendMessage(MessageRequest request)
The only thing left to do is specify the value of the type when we add a message to the list. For CCTray this is the option :Volunteer to fix build, in the integration itself, we must add the correct value to the breakers and the failing tasks.

Step 3 : expose the messagelist

This is merely adding a new xml element, which is a list, nothing special.
So in XmlReportAction.cs add this element :
xmlWriter.WriteStartElement("messages");

foreach (Message m in status.Messages)
{
xmlWriter.WriteStartElement("message");
xmlWriter.WriteAttributeString("text", m.Text);
xmlWriter.WriteAttributeString("kind", m.Kind.ToString());
xmlWriter.WriteEndElement();
}

xmlWriter.WriteEndElement();


Not so hard was it ?

Stay tuned for more in the future ...

Thursday, October 15, 2009

Wpf : Final encounter

I tried to enhance the display so that issues with attachments would have an icon (paperclip) next to it. To show and hide this image is easy, just use a converter. But getting the image to use an embedded resource was more difficult. For me this was the last drop.
I quit this WPF stuff for the moment, maybe I take it up again later, when the tools are more to todays standard, but from what I heard about VS2010, I doubt that it will be in the near future. Anyone who wants to take a look at the code, you can find the project at : Source Forge project
svn repository : https://jirawpf.svn.sourceforge.net/svnroot/jirawpf

maybe it needs some more comments, but you should get it to work.
If there are questions about the project itself, feel free to ask, I'll try to answer them.

Back to CCNet, that is a project I've neglected a bit, and needs some attention.

Friday, October 2, 2009

Wpf : style issues

Got the program almost like I want it. Encountered another big annoying WPF issue :
the order of the styles and datatemplates in a XAML file is of importance !
Take a look at the following example :
<DataTemplate x:Key="IssueDataTemplate" >
<ContentControl Style="{StaticResource IssueTemplate}"/>
</DataTemplate >

<Style x:Key="IssueTemplate" >
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal" >
<Label Content="{Binding Key}" Width="200"/>
<Label Content="{Binding Description}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You get a freaking runtime error : Unable to find style IssueTemplate ! ! !

To fix it, place the style first in the file, and next the datatemplate.

Questions :
1) Why does it throw a runtime error, and not a compile error, it is a static resource, meaning that it is known at design time, it is not loaded via an assembly at runtime (late binding technology).
2) Why an error in the first place? Back in 1990, it was of importance to place the procedures in correct order in the code, so the compiler could find them. But we're now in 2009! This is the way of working of 20 years ago!

When you code in any .Net language, Delphi, C, VB6, VB5, VB4 or even COBOL the place of a function in a class does not matter, hey even with partial classes, it does not even matter in which file they are! But WPF fails if the order is not ok.

I have a feeling that this issue will make the style files unorganized, and so making it errorprone :-(

sigh me wonder what is so fun and exciting about wpf, can someone enlighten me ? I do not grasp it.

Getting it to work

Found the courage again to code in this WPF world.
Reverted to use the ItemTemplate in the listbox, to get it to work. But now I have double XAML code : a datatemplate showing how a certain item is displayed, and a style showing how a certain item is displayed. The solution for this is to let the datatemplate use the style, so the layout is only defined once, like so :
<Style x:Key="IssueTemplate" >
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal" >
<Label Content="{Binding Key}" Width="200"/>
<Label Content="{Binding Description}" />
<Label Content="{Binding Votes}" />
<Label Content="{Binding Assignee}" />
<Label Content="{Binding Created}" />
<Label Content="{Binding Priority}" />
<Label Content="{Binding Reporter}" />
<Label Content="{Binding Status}" />
<Label Content="{Binding Votes}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<DataTemplate x:Key="IssueDataTemplate" >
<ContentControl Style="{StaticResource IssueTemplate}"/>
</DataTemplate >
The issue with the double click is not relevant anymore, I wanted to show a second window on double clicking an issue, but changed my mind. Now when you select an item in the listbox, the details of the selected issue are shown at the top of the screen. This is done by adding a ContentControl to the main window, binding its datacontext it to the same one as the listbox and setting the property IsSynchronizedWithCurrentItem to true. This works rather well. The code of the main window looks now like this :
<DockPanel>
<Expander VerticalContentAlignment="Top"
DockPanel.Dock="Left"
DataContext="{StaticResource CCNetProject}" >
<ContentControl Style="{StaticResource CCNetProjectTemplate}" />
</Expander>
<ContentControl DataContext="{StaticResource AllIssues}"
Style="{StaticResource IssueDetailTemplate}"
DockPanel.Dock="Top" />
<ListBox DockPanel.Dock="Bottom"
ItemsSource="{Binding Source={StaticResource AllIssues}}"
ItemTemplate="{StaticResource IssueDataTemplate}"
IsSynchronizedWithCurrentItem="True"
/>
</DockPanel>

As you can see, there is nothing in the main window about how a certain item is displayed, no coloring, borders, ... All this is done is in the styles. I'll see how far I get with this approach. I'm now busy with showing the details of a certain issue, when that is done the most important functionality of the program is done, making it possible to give the app a more polished look.
Stay tuned ...