Joshua Marinacci’s second JavaFX doodle is an animated tabbed rectangle. When pressing on a rectangle, a rectangle appears and expands. Once the rectangle reaches its full height, an animated tab grows out of the rectangle. As with the first JavaFx Doodle, Andres Almiray implemented the second JavaFx Doodle in Groovy.
Here’s my implementation of Doodle #2 in WPF:

The complete project is available
here.
For this doodle, I created a custom control for the tab rectangle. Creating this control actually took me a couple of attempts. First I created the control in Expression Blend 2.5 by combining a rectangle and a couple of paths for the tab. This control worked but it didn’t leave me with something I could animate - the path segments were already precomputed. My next try focused on the animation aspects of the tab. I added “Arc” and “TabSize” dependency properties to provide some parameters that could be animated. I tried to produce the tabbed rectangle geometry within XAML, but either because of limitations in XAML or more likely in my skills, I had to resort to generating the geometry in C#. For the geometry, I added a third dependency property, “TabGeometry”. The tab geometry is automatically updated when any of the “Arc”, “TabSize”, “Height”, or “Width” properties are changed.
Here is the XAML for the tabbed rectangle:
<UserControl x:Class="Doodle2.TabRect" x:Name="UserControl">
<Canvas>
<Path Stroke="Black" StrokeThickness="3" Data="{Binding TabGeometry, ElementName=UserControl}">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="Blue" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
</Canvas>
</UserControl>
Most of the code-behind is boilerplate; see the full project for the details. The only portion that is interesting is the creation of the tabbed rectangle geometry which is done in the ComputeGeometry method:
private void ComputeGeometry()
{
RectangleGeometry rect = new RectangleGeometry(new Rect(0, 0, Width, Height), Arc, Arc);
PathSegmentCollection tabSegments = new PathSegmentCollection();
tabSegments.Add(new LineSegment(new Point(Width / 2, Height + TabSize * 1.5), true));
tabSegments.Add(new LineSegment(new Point(Width / 2 + TabSize, Height), true));
PathFigure tabFigure = new PathFigure(new Point(Width / 2 - TabSize, Height), tabSegments, false);
PathFigureCollection tabFigures = new PathFigureCollection();
tabFigures.Add(tabFigure);
PathGeometry tab = new PathGeometry(tabFigures);
TabGeometry = new CombinedGeometry(tab, rect);
}
As you can see, WPF provides enough classes and methods to make creating this geometry trivial. Thanks to Charles Petzold’s Applications = Code + Markup book for usage examples.
Now that the tabbed rectangle is finished, it needs to be hosted and animated. I use the following XAML within a Window to display the tabbed rectangle and star. Thanks to Mark Heath for the XAML star.
<Canvas x:Name="LayoutRoot">
<Doodle2:TabRect Opacity="0" Width="100" Height="50" x:Name="tabRect" Canvas.Left="20" Canvas.Top="20"/>
<Path x:Name="path" Stroke="#000080" Fill="#FFFF00" StrokeThickness="3" StrokeStartLineCap="Round"
StrokeEndLineCap="Round" StrokeLineJoin="Round" Canvas.Top="69" Canvas.Left="163"
Data="M 0,0 l 10,0 l 5,-10 l 5,10 l 10,0 l -7,10 l 2,10 l -10,-5 l -10,5 l 2,-10 Z"/>
</Canvas>
The animation storyboard is very simple. The only interesting point is that the begin time for animating the TabSize is delayed:
<Storyboard x:Key="TabAnimate">
<DoubleAnimation Storyboard.TargetName="tabRect" Storyboard.TargetProperty="(FrameworkElement.Height)"
From="0" To="100" Duration="0:0:01" BeginTime="0:0:00"/>
<DoubleAnimation Storyboard.TargetName="tabRect" Storyboard.TargetProperty="(FrameworkElement.Opacity)"
From="0" To="100" Duration="0:0:01" BeginTime="0:0:00"/>
<Int32Animation Storyboard.TargetName="tabRect" Storyboard.TargetProperty="(Doodle2:TabRect.Arc)"
From="0" To="10" Duration="0:0:01" BeginTime="0:0:00"/>
<Int32Animation Storyboard.TargetName="tabRect" Storyboard.TargetProperty="(Doodle2:TabRect.TabSize)"
From="0" To="0" Duration="0:0:01" BeginTime="0:0:00"/>
<Int32Animation Storyboard.TargetName="tabRect" Storyboard.TargetProperty="(Doodle2:TabRect.TabSize)"
From="0" To="10" Duration="0:0:00.3" BeginTime="0:0:01"/>
</Storyboard>
Finally, the animation is triggered via a MouseDown event:
<EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="path">
<BeginStoryboard Storyboard="{StaticResource TabAnimate}"/>
</EventTrigger>
As with the first doodle, I think the WPF implementation stacks up well against the JavaFX and Groovy GraphicsBuilder implementations.