Calculating the height of text in a styled TextArea

I’d like to have a styled text TextArea without scrollbars. Instead, I want the height of the TextArea to grow or diminish as necessary to just fit the text as the user types. I can’t assume a single lineheight because the user can change the size of individual characters or words. A solution in native Xojo or by using MBS would be welcome.

Do you mean like this? Ohanaware App Kit 2021 Release 3 demo video - YouTube

It should play from the point where I demo a expanding text area.

2 Likes

I don’t find a function like “boundingRectWithSize” in Objective-C to do this.
In my app. RealCADD, I do it by parsing all StyleRun of the StyledText and calculate length and height of each word to calculate the height of all text.

Unfortunately the usual method (in textChanged event) works only with fixed font height and name.

Private Function setTxtHeight(s as String, tWidth as Integer, fName as String, fSize as Integer) As Integer
dim p as new Picture(32,32)
dim g as Graphics = p.Graphics
g.TextFont = fName
if fSize = 0 then fSize = 14//or whatever
g.TextSize = fSize
Return g.StringHeight(s,tWidth) + g.TextAscent
End Function

Yes, that’s what I mean. But as I said, it must be able to deal with multiple fonts and font sizes in the same TextArea. Can your code deal with that?

I considered this, too. But how do you take into account the textarea width and word wrapping?

I haven’t tested it much but here is some MBS based code for macOS which you can put into the TextChanged event:

  Dim nsTextViewObj As NSTextViewMBS
  
  nsTextViewObj = Me.NSTextViewMBS
  
  Me.Height = nsTextViewObj.layoutManager.usedRectForTextContainer(nsTextViewObj.textContainer).Height + 4

If you want to put the code in other places (such as when changing the style of a selection) you might have to trigger a refresh first so that the layout manager does its work on the updated text.

1 Like

I’ve done some quick tests and it seems to work perfectly.

Thank you very much!

1 Like

Thanks, keving for that post, it works fine!

but, got a problem:
i want to show the textarea by myTextArea.viewonly = true but with the calculated hight.
Problem was that the TextChange event only fires if a user is typing the value.
i was not able to trigger this event if i just showed the control and entered the text by a method.

so, i added a GotFocus, triggered the same code from there, added a Timer.Callater(10, Addressof, myMethod) and inserted in myMethod a myTextArea.setFocus and that triggered the code again and so it works for now.

but … puh!

ist there not a better way?

I created a new project with a read-only TextArea, and in the window Opening event used TextArea1.text = “Hello World”. The TextArea’s TextChanged event fired.

Thanks, Jonathan!
then it was that i filled up the textarea on a other way.
meanthwile i draged the code in a method, replaced me by a param and so i was able to trigger it from outside.