7.3 Builder

A builder is an object specialized to construct one or several types of object, the type of the constructed object depends on the nature of the inputs sent to the builder. Explained differently, depending on input received by the builder, it will figure out what and how to construct a new object with the provided inputs.

In DrGeo there is a whole hierarchy of 39 builders. The abstract class DrGMathItemBuilder provides the general mechanism through template methods. When an object is added to the builder, first it is asked if it is wanted or not. Next, once the object is added to the builder, it is asked if the builder is ready to build a new object, if so an event is propagated to whatever is listening

add: aMathItemCollection at: aPoint
"
Add a math item in the selection list of the builder, aPoint is the position where the action took place. Return true if mathItem accepted
"
^ (self isWanted: aMathItemCollection at: aPoint)
   and: [
      self addItem: aMathItemCollection at: aPoint.
      "Are we done? If so notify our dependent"
      self readyToBuild ifTrue: [self triggerEvent: #readyToBuild].
      true]

Let’s look at the subclass DrGBuilderMiddle, a builder to construct the middle of two points or a segment.

DrGMathItemBuilder subclass: #DrGMiddleBuilder
   instanceVariableNames: 'pointA pointB segment'
   classVariableNames: ''
   poolDictionaries: ''
   category: 'DrGeo-Presenter-Builder'

The methods are overridden to fit the task. The middle builder filters items which are either point or segment and depending on the history of the already added item to the builder.

isWanted: aMathItemCollection
^ aMathItemCollection notEmpty 
   and: [
      (aMathItemCollection first isPointItem and: [aMathItemCollection first ~= pointA])
      or: [aMathItemCollection first isSegmentItem and: [pointA isNil]] ]

Observe a segment is not wanted if a point – pointA – was already provided to the builder.

Adding an item to a builder also depends on the history of added item, pointB will be set once pointA is already known:

addItem: aMathItemCollection at: aPoint
super addItem: aMathItemCollection at: aPoint.
aMathItemCollection first isPointItem 
   ifTrue: [
      pointA ifNil: [
         pointA := aMathItemCollection first.
         ^ self].
      pointB ifNil: [
         pointB := aMathItemCollection first.
         ^ self ] ]
   ifFalse: [segment := aMathItemCollection first]

Once the segment or the point A and B are known, we are ready to build middle point:

readyToBuild
^ segment notNil or: [pointA notNil and: [pointB notNil]]

In the DrGeo GUI, each builder is associated with a tool activated by a button or a menu entry. A builder is very handy to both give feedback to the user and to interpret what the user wants to do.

For example with the DrGMiddleBuilder: