Balloon Text – using Decorators

image  Recently I had to render some text inside a Balloon, similar to the balloons that you see in Comic Strips. They are also called Speech Balloons.

 image  My initial reaction was to use the ScaleNine technique that you have in Adobe Flex. ScaleNine splits the graphic that you see on the left into a grid of 9 tiles, like the TicTacToe grid. As the text grows in length, only the central tiles scale, not the corner tiles. This gives the desired behavior for the balloon. However, using this technique with WPF turns out to be cumbersome. It seemed like introducing a lot of complexity just to get a simple scalable balloon.

Then it struck me that Decorators would be an elegant solution for this problem. We already have decorators like Border, Viewbox, which override the OnRender() method and draw the lines and curves. Creating a similar decorator for the balloon text seemed like a good solution.

The BalloonDecorator

One of the first steps was to extend the Decorator class and override the methods: OnRender(), MeasureOverride() and ArrangeOverride(). Next I defined some DependencyProperties like Background, CornerRadius, BorderThickness, BorderBrush and PointerLength. Here CornerRadius, BorderThickness and PointerLength properties had extra metadata flags: FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure

In the OnRender() method, I use a StreamGeometry class to create the geometry of the balloon. StreamGeometry is a lightweight alternative to PathGeometry, since I don’t need any of the data-binding and layout capabilities. The balloon is basically a bunch of lines and curves.

image

The curvature depends on the CornerRadius property and the PointerLength defines the horizontal length of the Pointer. You can also think of the pointer length as the horizontal gap between the tip of the pointer and the left edge of the rounded rectangle.

In MeasureOverride(), I include the PointerLength, BorderThickness and the dimensions of the rectangle and then return the sum total as the size.

In ArrangeOverride() I need to ensure that my child element is arranged inside the bounds of the balloon. So the child is actually offset by the PointerLength and the BorderThickness. So the arrange-rect for the child is the inner rectangle of the balloon.

Using the BalloonDecorator

The balloon text in the first figure can be created with the following XAML:

 <local:BalloonDecorator PointerLength="20"
                         CornerRadius="10"
                         BorderBrush="Black">
  <Grid>
  <TextBlock Text="Hello World! - Most tutorials on programming ...."
                HorizontalAlignment="Center"
                FontStyle="Italic"
                TextWrapping="Wrap"
                TextTrimming="WordEllipsis"/>
  </Grid>
 </local:BalloonDecorator>

Here are some more examples of the BalloonDecorator in action.

 image

image

image

 

The next steps would be to have some extra customizations on the direction of the pointer and also the appearance. For example I could have a more curvy pointer pointing in the North-East direction!

Similar Posts:

10 responses to “Balloon Text – using Decorators”

  1. Pavan Podila

    I have posted the code on http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!411.entry

  2. (no name)

    Great Work! Code available yet?

  3. (no name)

    Great Work! Code available yet?

  4. (no name)
    Hi Pavan, I’d love to see the code for this too!
  5. Ahmed Chaudhary

    I would love to see the code too

    -Ahmed

  6. (no name)
    plus one on the code!
  7. asianBMW
    hi there.. is the code available yet? surfing and seeing lots of samples of wpf.. hopefully have time to experiment with all of them!
  8. Pavan Podila

    Hi Oscar,
         I will put out the source code soon. I found a subtle rendering bug with the balloon text which I have fixed and I am testing it out a little more. Hopefully I wont keep you waiting for too long ;)

  9. Oscar
    would love to see the code
  10. Pavin Podila: http://codeplex.com/FluidKit - WPF controls, etc... - Rob Relyea - Xamlified

    [...] ( Part 1, Part 2 [...]

Leave a Reply