Click here to Skip to main content
15,891,136 members
Articles / Desktop Programming / Windows Forms

Object-oriented Printing with Inka, Part 1

Rate me:
Please Sign up or sign in to vote.
4.00/5 (4 votes)
27 Feb 2009LGPL35 min read 34.4K   396   28  
The basics of Inka, an open source printing component
Imports Inka.Core.Utils

Namespace Core.Layout

	'''' <summary>
	'''' Used to execute the callback when the <see cref="PositionStack">PositionStack</see> is ready to insert an element.
	'''' </summary>
	'''' <remarks>When the <see cref="PositionStack.AppendElement">PositionStack.AppendElement</see> method </remarks>
	'Public Delegate Sub PositionStackCallbackDelegate(ByVal stack As PositionStack, ByVal element As Element)

	''' <summary>
	''' This class encapsulates the stack of PositionData objects associated with the nested elements. The first element in the stack corresponds to the current page, the bottom one -- to the innermost element.
	''' </summary>
	''' <remarks>Thisclass is used for determining the next available position for an element.</remarks>
	Public Class PositionStack
		Inherits Stack(Of IPositionData)

		Private _positions As New Collections.Generic.Dictionary(Of IElement, Utils.Shift)
		Public ReadOnly Property ElementPositions() As Collections.Generic.Dictionary(Of IElement, Utils.Shift)
			Get
				Return Me._positions
			End Get
		End Property

		Function GetPosition() As Shift
			Dim result As Shift
			For Each item In Me
				result += item.Origin + item.Current
			Next
			Return result
		End Function

		Sub ResetStack()
			For Each item In Me
				item.Current = New Shift()
				item.Size = New Rectangle()
			Next
		End Sub

		'Sub ShiftCurrent(ByVal value As Integer)
		'	Me.CurrentData.Current += New Shift(0, value)
		'End Sub

		Sub AppendElement(ByVal element As Element, ByVal callback As Action(Of Element, PositionStack))   'TODO: change the agument to some interface like IElementWithLayout
			AppendElement(element, callback, Function(elt) elt.Unbreakable)
		End Sub

		Public Sub AppendElement(ByVal element As Element, ByVal callback As Action(Of Element, PositionStack), ByVal atomic As Predicate(Of Element))
			If atomic.Invoke(element) Then
				If callback IsNot Nothing Then callback.Invoke(element, Me)
				Me.CurrentData.Size = New Rectangle(0, Math.Max(Me.CurrentData.Size.Height, Me.CurrentData.Current.y + element.TakenSpace.Height))
				Me.CurrentData.Current += element.PushValue
			Else
				Me.Push(New PositionData(element.Position))
				Me.CurrentData.Size = element.Size
				For Each child In DirectCast(element, CompoundElement).Children
					Me.AppendElement(child, callback, atomic)
				Next
				Dim size = Me.CurrentData.Size + New Rectangle(0, element.Position.y) 'equivalent to PushValue
				Me.Pop()
				Me.CurrentData.Size = New Rectangle(0, Math.Max(Me.CurrentData.Size.Height, Me.CurrentData.Current.y + size.Height))
				Me.CurrentData.Current += size 'TODO: this is only if element.PushesDown
			End If
		End Sub

		ReadOnly Property CurrentData() As IPositionData
			Get
				Return Me.Peek()
			End Get
		End Property

	End Class
End Namespace

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer GeekSoft
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions