Perspective : polygons and honeycombs

Perspective : polygons and honeycombs

Regular polygons

The PolygonElement class of the Perspective for Silverlight library makes it possible to draw regular polygons.

The SideCount property determines the number of faces. Its default value is 6. The InitialAngle property determines the angle of the figure. With an angle of 30 degrees, the base of a hexagon is a peak. For the rest, PolygonElement has the classical properties of a Shape (although for technical reasons it inherits from Panel) : Fill, Stroke and StrokeThickness.

PolygonElement

<UserControl.Resources>
  <Style x:Key="PolygonElementStyle" TargetType="pc:PolygonElement">
    ...
    <Setter Property="Stroke" Value="{StaticResource BasicShapeStroke}" />
    <Setter Property="StrokeThickness" Value="2.0" />
    <Setter Property="Fill" Value="{StaticResource BasicShapeFill}" />
  </Style>
</UserControl.Resources>
...
<pc:PolygonElement 
  Style="{StaticResource PolygonElementStyle}"
  SideCount="3"/>

The code of the PolygonElement class is a good example of custom drawing. Unlike WPF, it is not possible to create a custom drawing class inherited from Shape in Silverlight 2 and 3 (beta 1). Indeed, the code definition of the geometry is defined in the native, non-extensible, code kernel. The technique used in Perspective is to inherit the Panel class, and to build a Path object, child of the Panel.

Honeycomb layout

As a beekeeper, I've naturally choosed a layout as a honeycomb to show how to build custom panels through the BeePanel and Beegrid classes of the Perspective library.

These panels define a grid of hexagonal cells, composed of rows and columns (slightly shifted because of the hexagonal shapes). The SideLength property determines the size of one side of a cell (100 pixels by default). The number of cells can be determined automatically from the dimensions of the panel, or manually through the RowCount and ColumnCount properties.

BeePanel organizes automatically the child elements in the successive cells, from the upper left corner and making returns, as a WrapPanel.

BeePanel

<pc:BeePanel 
  ColumnCount="3" RowCount="3" 
  SideLength="60"
  Margin="10"
  HorizontalAlignment="Left" VerticalAlignment="Center">
  <Grid>
    <pc:PolygonElement 
      Style="{StaticResource PolygonStyle}"/>
    <Button 
      Style="{StaticResource ButtonStyle}" 
      Content="0"/>
  </Grid>
  <Grid>
    <pc:PolygonElement 
      Style="{StaticResource PolygonStyle}"/>
    <Button 
      Style="{StaticResource ButtonStyle}" 
      Content="1"/>
  </Grid>
  ...
</pc:BeePanel>

BeeGrid will position the child in cells specified by the Column attached properties and Row, like a Grid. BeeGrid inherits from BeePanel.

BeeGrid

<pc:BeeGrid 
  Name="beeGrid"
  ColumnCount="3" RowCount="3" 
  Margin="10"
  SideLength="60"
  HorizontalAlignment="Left" VerticalAlignment="Center">
  <pc:PolygonElement 
    Style="{StaticResource PolygonStyle}"
    pc:BeeGrid.Row="0"
    pc:BeeGrid.Column="0"/>
  <pc:PolygonElement 
    Style="{StaticResource PolygonStyle}"
    pc:BeeGrid.Row="0"
    pc:BeeGrid.Column="1"/>
  ...
</pc:BeeGrid>

Demo

The BeePanel and BeeGrid source code illustrates the creation of custom panels. In particular, it shows how to manage the 2 phases of the children arrangement system :

  • The measurement phase (MeasureOverride method) in which the panel code calls the Measure method for each item, which states in its DesiredSize property the size it would like to have.
  • The arrangement phase (ArrangeOverride method) in which the panel states the available space. The panel code divides the space between the different elements, calling their Arrange method.

About this article

Author : Olivier Dewit.

History :