Enhancing text with basic text attributes

Text, like the one in this very snippet, is modelled as BlText Object subclass: #BlText uses: TBlDebug + TBlTextStyleable instanceVariableNames: 'announcer' classVariableNames: '' package: 'Bloc-Text-Text' . A simple way to get a text object is to use String>>#asRopedText asRopedText ^ BlRunRopedText string: self .

text := String loremIpsum asRopedText.
  

The text object provides an API for defining attributes:

textWithGlobalAttributes
	<gtExample>
	| text |
	text := String loremIpsum asRopedText.
	text
		attributes: {BlFontFamilyAttribute named: 'Source Code Pro'.
				BlFontWeightAttribute bold.
				BlTextForegroundAttribute paint: Color blue}.
	self assert: (text attributesAt: 1) size equals: 3.
	self assert: (text attributesAt: text size) size equals: 3.
	^ text
    

The script above defines attributes for the entire text. Of course, it is possible to add attributes only for a range of a text. For example:

textWithAttributesOnARange
	<gtExample>
	| text |
	text := String loremIpsum asRopedText.
	(text from: 15 to: 45)
		attributes: {BlFontFamilyAttribute named: 'Source Code Pro'.
				BlFontWeightAttribute bold.
				BlTextForegroundAttribute paint: Color blue}.
	self assert: (text attributesAt: 1) isEmpty.
	self assert: (text attributesAt: 15) size equals: 3.
	self assert: (text attributesAt: 45) size equals: 3.
	self assert: (text attributesAt: 46) isEmpty.
	^ text
    

Of course, attributes can also overlap. Take a look at the example below:

textWithOverlappingFonts
	<gtExample>
	| text |
	text := '1234567890' asRopedText.
	(text from: 2 to: 6)
		attributes: {BlFontFamilyAttribute named: 'Source Code Pro'.
				BlFontWeightAttribute bold.
				BlTextForegroundAttribute paint: Color red}.
	(text from: 4 to: 8)
		attributes: {BlFontFamilyAttribute named: 'Source Code Pro'.
				BlFontEmphasisAttribute italic.
				BlTextForegroundAttribute paint: Color blue}.
	self assert: (text attributesAt: 1) isEmpty.
	self assert: (text attributesAt: 2) size equals: 3.
	self assert: (text attributesAt: 4) size equals: 4.
	self assert: (text attributesAt: 6) size equals: 4.
	self assert: (text attributesAt: 8) size equals: 3.
	self assert: (text attributesAt: text size) isEmpty.
	^ text
    

In this example, the blue color overrides the red colors for a couple of characters. In that situation, we the BlTextForegroundAttribute BlTextAttribute subclass: #BlTextForegroundAttribute instanceVariableNames: 'paint' classVariableNames: '' package: 'Bloc-Text-Text-Attributes' is replaced by the new one. If you want to understand how the structure looks under the hood try investigating the All attributes and the Intervals views of the text object.

In the above examples we instantiated the text attributes objects explicitly, but you actually do not have to do that. The TBlTextStyleable Trait named: #TBlTextStyleable instanceVariableNames: '' package: 'Bloc-Text-Text-Support' offers a fluent API to work with most attributes. For example, the above example can look like this:

textWithOverlappingFontsUsingTheStyleableAPI
	<gtExample>
	| text |
	text := '1234567890' asRopedText.
	(text from: 2 to: 6)
		fontName: 'Source Code Pro';
		bold;
		foreground: Color red.
	(text from: 4 to: 8)
		fontName: 'Source Code Pro';
		italic;
		foreground: Color blue.
	self assert: (text attributesAt: 1) isEmpty.
	self assert: (text attributesAt: 2) size equals: 3.
	self assert: (text attributesAt: 4) size equals: 4.
	self assert: (text attributesAt: 6) size equals: 4.
	self assert: (text attributesAt: 8) size equals: 3.
	self assert: (text attributesAt: text size) isEmpty.
	^ text
    

It is possible to have attributes that go beyond colors or font names. We call them adornments. Take a look at Working with text adornments to learn more.