Platforms to show: All Mac Windows Linux Cross-Platform
/MacCG/CoreText/CoreText Dynamic Text Height
Required plugins for this example: MBS MacBase Plugin, MBS MacCF Plugin, MBS MacCocoa Plugin, MBS MacCG Plugin, MBS Main Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /MacCG/CoreText/CoreText Dynamic Text Height
This example is the version from Mon, 15th Nov 2015.
Project "CoreText Dynamic Text Height.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Löschen"
Const kFileQuit = "Beenden"
Const kFileQuitShortcut = ""
End Class
Class Window1 Inherits Window
Control Canvas1 Inherits Canvas
ControlInstance Canvas1 Inherits Canvas
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect)
// create a font, quasi systemFontWithSize:24.0
dim sysUIFont as CTFontMBS = CTFontMBS.CreateUIFontForLanguage(CTFontMBS.kCTFontUIFontSystem, 18.0)
// create a naked string
dim text as string = "Edit Text and change Font size."
// blue
dim cgColor as CGColorMBS = CGColorMBS.CreateGenericRGB(0.0, 0.0, 1.0)
// single underline
dim underline as integer = CoreTextMBS.kCTUnderlineStyleSingle
// pack it into attributes dictionary
dim attributesDict as new Dictionary
attributesDict.Value(CoreTextMBS.kCTFontAttributeName) = sysUIFont
attributesDict.Value(CoreTextMBS.kCTForegroundColorAttributeName) = cgColor
attributesDict.Value(CoreTextMBS.kCTUnderlineStyleAttributeName) = underline
// make the attributed string
dim cfDic as new CFDictionaryMBS(attributesDict)
dim cfStr as new CFStringMBS(text)
dim stringToDraw as CFAttributedStringMBS = CFAttributedStringMBS.Create( cfStr, cfDic)
// now for the actual drawing
dim CGContextHandle as integer = g.Handle(g.HandleTypeCGContextRef)
dim CGContext as CGContextMBS = CGContextMBS.contextWithCGContext(CGContextHandle)
CGContext.SaveGState
// reset text matrix
dim a as CGAffineTransformMBS = CGAffineTransformMBS.Identity
CGContext.TextMatrix = a
// draw
dim line as CTLineMBS = CTLineMBS.CreateWithAttributedString(stringToDraw)
dim x as integer = 10
dim y as integer = 10
// plus text height
y = y + 24
// swap y
y = g.Height - y
CGContext.TextPosition = new CGPointMBS(x, y)
line.Draw(CGContext)
CGContext.RestoreGState
CGContext.Flush
// clean up
End EventHandler
End Control
Control Timer1 Inherits Timer
ControlInstance Timer1 Inherits Timer
EventHandler Sub Action()
Canvas1.Invalidate
End EventHandler
End Control
Control Canvas2 Inherits Canvas
ControlInstance Canvas2 Inherits Canvas
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect)
dim longText as string = TextArea1.Text
dim s as new NSMutableAttributedStringMBS
call s.initWithString(longText)
Dim FontSize As Integer = Slider1.Value
// setup font
dim helvetica as CTFontMBS = CTFontMBS.CreateWithName("Helvetica", FontSize)
dim r1 as new NSRangeMBS(0, s.Length)
s.addattribute(CoreTextMBS.kCTFontAttributeName, helvetica, r1)
// add some color
dim greenColor as CGColorMBS = CGColorMBS.CreateGenericRGB(0.19, 0.56, 0.20)
s.addattribute(CoreTextMBS.kCTForegroundColorAttributeName, greenColor, r1)
// add color red to last three characters
if s.Length > 2 then
dim redColor as CGColorMBS = CGColorMBS.CreateGenericRGB(1, 0, 0)
dim r2 as new NSRangeMBS(s.Length - 3, 3)
s.addattribute(CoreTextMBS.kCTForegroundColorAttributeName, redColor, r2)
end if
// centre text
dim p as NSParagraphStyleMBS = NSParagraphStyleMBS.defaultParagraphStyle
dim p2 As NSMutableParagraphStyleMBS = p.mutableCopy
p2.setAlignment NSParagraphStyleMBS.NSCenterTextAlignment
s.addattribute(CoreTextMBS.kCTParagraphStyleAttributeName, p2, r1)
// layout master
dim cs as CFAttributedStringMBS = s.AsCFAttributedString
dim framesetter as CTFramesetterMBS = CTFramesetterMBS.CreateWithAttributedString(cs)
// calculate height required to display all text
dim sizeOfWidth As CGSizeMBS = CGSizeMBS.Make(g.Width, 10000) // How do I set 'CGFloat_Max' instead of 10000? [Question]
dim fitRangeLocation, fitRangeLength As Integer
dim dEmpty As New Dictionary
dim sizeOfFrame As CGSizeMBS = framesetter.SuggestFrameSizeWithConstraints(0, 0, dEmpty, sizeOfWidth, fitRangeLocation, fitRangeLength)
// Resize height of window to fit all of text
dim NewWinHeight As Integer = sizeOfFrame.Height + me.Top
self.Height = NewWinHeight
// create form
dim ColumnPath as new CGMutablePathMBS
dim Rect as new CGRectMBS(0, 0, g.Width, g.Height)
ColumnPath.AddRect nil, Rect
// create frame
dim Frame as CTFrameMBS = framesetter.CreateFrame(0, 0, ColumnPath, nil)
// get context
dim CGContextHandle as integer = g.Handle(g.HandleTypeCGContextRef)
dim CGContext as CGContextMBS = CGContextMBS.contextWithCGContext(CGContextHandle)
CGContext.SaveGState
// reset text matrix
dim a as CGAffineTransformMBS = CGAffineTransformMBS.Identity
CGContext.TextMatrix = a
// draw frame
Frame.Draw(CGContext)
// cleanup
CGContext.RestoreGState
CGContext.Flush
End EventHandler
End Control
Control TextArea1 Inherits TextArea
ControlInstance TextArea1 Inherits TextArea
EventHandler Sub TextChange()
Canvas2.Invalidate
End EventHandler
End Control
Control Slider1 Inherits Slider
ControlInstance Slider1 Inherits Slider
EventHandler Sub ValueChanged()
Label2.Text = Str(me.value)
Canvas2.Invalidate
End EventHandler
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control Label2 Inherits Label
ControlInstance Label2 Inherits Label
End Control
Note "About"
Thanks to Mark Franken from Sounds In Sync for creating this example project.
Shows how to correctly caluclate the text height.
End Class
MenuBar MenuBar1
MenuItem FileMenu = "&Ablage"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Bearbeiten"
MenuItem EditUndo = "&Rückgängig"
MenuItem UntitledMenu1 = "-"
MenuItem EditCut = "&Ausschneiden"
MenuItem EditCopy = "&Kopieren"
MenuItem EditPaste = "&Einfügen"
MenuItem EditClear = "#App.kEditClear"
MenuItem UntitledMenu0 = "-"
MenuItem EditSelectAll = "&Alles auswählen"
End MenuBar
End Project
See also:
The items on this page are in the following plugins: MBS MacCG Plugin.