RenderPolicy

The presentation of a HyperComponent is built by a RenderPolicy. Different subclasses of RenderPolicy render HyperComponents in different ways.

All RenderPolicies can construct a VisualLink that ties together a HyperComponent with the VisualComponent that represents it. This VisualLink is then put into a wrapper, such as a BoundedWrapper, that will eventually be put into a view to be displayed.

HyperRenderer assigns a RenderPolicy to each HyperComponent. The most important method that must be implemented by all subclasses of RenderPolicy is #formatInto:. The parameter to this method is aContainer. RenderPolicy constructs a VisualLink, puts the VisualLink into a Wrapper, and then sends a #addWrapper to aContainer. Below is the implementation of ImagePolicy that is used to render a WebComponent with the type #image.

formatInto: aContainer | vLink anImage vComponent | anImage := self getImage. vLink := (self defaultVisualLink) structuralComponent: self component; visualComponent: anImage. vComponent := self wrapperClass on: vLink. aContainer addWrapper: vComponent. ^vComponent

The method #formatCollection:into:width: is a powerful method to format a collection of HyperComponents. This method takes care of whether the representation of consecutive HyperComponents can be combined together into one paragraph. The implementation is shown below:

formatCollection: aCollection into: aContainer width: anInteger "Format each element in a collection of HypertextComponents. #isHText checks if the representations of consecutive HyperComponents may be combined into one paragraph. " | iString textWidth vComp | iString := self defaultTaggedString new. textWidth := anInteger. aCollection do: [:each | | fm | fm := each formatPolicy. (fm isHText and: [fm isText]) ifTrue: [iString := iString , fm makeTaggedString] ifFalse: [iString size > 0 ifTrue: [self composeTaggedString: iString into: aContainer width: textWidth]. textWidth := anInteger. fm maxWidth: textWidth; maxWidthFlag: false. vComp := fm formatInto: aContainer. vComp notNil ifTrue: [textWidth := textWidth - vComp preferredBounds width. textWidth < 1 ifTrue: [textWidth := anInteger]]. iString := self defaultTaggedString new]]. iString size > 0 ifTrue: [vComp := self composeTaggedString: iString into: aContainer width: textWidth]. ^vComp

In the above implementation, iString is first initialized to a StructuredText which serves as a buffer for text representations. Then, for each RenderPolicy, it is checked if the visual representation is a text and if this text can be concatenated with the text represenation of other RenderPolicies. If they are both true, the StructuredText represented by that RenderPolicy is concatenated with the StructuredText in the buffer iString. If the RenderPolicy doesn't have a text representation or its text representation cannot be combined with consecutive RenderPolicy, then the StructuredText already in the buffer is output into aContainer by #composeTaggedString:into:width:. This whole process goes on until all RenderPolicies have taken actions.

The section on The story starts with a hypertext document contains an example, diagrams, and internal strucutres of rendering a HTML document.