Visualizing LINQ Sequences with GDI+, Page 2
The utility is capable of producing rectangle sub-divisions as suggested by the roughly created grid in the comment in the first part of the listing. You can specify the number of vertical and horizontal sub-rectangles, which horizontal and vertical sub-rectangle to return, and CenterRect (at the end) will return a rectangle centered vertically and horizontally within another rectangle.
The reason shared methods were used is that the Rectangles class itself stores no data; that is, it contains no fields, properties, or events. Following a general OOP rule such a class is naturally specified as a class containing all shared members.
Defining a State-Full Rectangle Manager
Next, I wanted to able to track individual rectangles, so a state-full RectangleManager was defined. This class keeps track of its horizontal and vertical sub-rectangles (with hSegments and vSegments), the desired padding between rectangles, and the original outer rectangle. This class is useful for keeping track of a specific rectangle set being used. Listing 2 contains the RectangleManager.
Listing 2: The RectangleManager is state-full—keeping track of the rectangle under management.
Imports System.Collections
Public Class RectangleManager
'Implements IEnumerator
' note to self - implement IEnumerator so we can do a foreach
' over the segments
Public Sub New(ByVal Rect As Rectangle, _
ByVal hSegments As Integer, ByVal vSegments As Integer)
Me.Rect = Rect
Me.vSegments = vSegments
Me.hSegments = hSegments
End Sub
Public Sub New(ByVal Rect As Rectangle, _
ByVal hSegments As Integer, _
ByVal vSegments As Integer, ByVal padding As Integer)
Me.Rect = Rect
Me.vSegments = vSegments
Me.hSegments = hSegments
Me.padding = padding
End Sub
Private Rect As Rectangle
Private vSegments As Integer
Private hSegments As Integer
Private padding As Integer = 4
Public Function GetSubRect(ByVal xSegment As Integer, _
ByVal ySegment As Integer) As Rectangle
Return Rectangles.GetSubRect(Rect, xSegment, ySegment, _
hSegments, _
vSegments, padding)
End Function
Public Function CenterRect(ByVal size As SizeF, _
ByVal xSegment As Integer, _
ByVal ySegment As Integer)
Return Rectangles.CenterRect(size, GetSubRect(xSegment, _
ySegment))
End Function
End Class
Visualizing a LINQ Query with the Rectangle Manager
A LINQ query returns a sequence. (Think collection!) By using ellipses, you can visualize the sequence as a linear row of circles with each circle containing the text (or a representation of the text) in the circle itself. Listing 3 shows the form for representing the sequence visually, and Listing 4 contains a concrete behavior class that contains the draw-sequence behavior. (You can look up the State Behavior Pattern on dofactory.com or the GoF book on Design Patterns.)
Listing 3: The Form using a state behavior pattern; the Form shows the visual representation of the LINQ query.
Public Class Form1
Private state As MyStatePattern
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
state = New DrawSequenceState(p)
End Sub
Private p As Pen = New Pen(Color.Red, 4)
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles Me.Paint
state.Draw(e.Graphics, Font)
End Sub
Private Sub DrawRectanglesToolStripMenuItem_Click(ByVal _
sender As System.Object, _
ByVal e As System.EventArgs) Handles _
DrawRectanglesToolStripMenuItem.Click
state = New DrawRectState(p)
Invalidate()
End Sub
Private Sub DrawEllipsesToolStripMenuItem_Click(ByVal sender _
As System.Object, _
ByVal e As System.EventArgs) Handles _
DrawEllipsesToolStripMenuItem.Click
state = New DrawEllipseState(p)
Invalidate()
End Sub
Private Sub DrawSequenceToolStripMenuItem_Click(ByVal sender _
As System.Object, _
ByVal e As System.EventArgs) Handles _
DrawSequenceToolStripMenuItem.Click
state = New DrawSequenceState(p)
Invalidate()
End Sub
End Class
