This method has been used successfully from Omnis Studio 5.32 through 11.2 --- in other words, properly battle-tested.
It provides a robust way to dynamically size a text field and its containing window based on: - Window resizing - Text content - Carriage returns - Style commands - Embedded bitmap elements
The approach follows a simple principle:
Let Omnis handle layout wherever possible.
Instead of forcing sizes: - Use kPagedPane auto-resizing - Use edgefloat - Use style sheets - Calculate only what Omnis cannot
Window
โโโ kPagedPane (messagePane)
โโโ Background object (iMessage)
โโโ Calculation: [iMessage]
โโโ Instance variable: iMessage
messagePane
kefPosnClient (or similar)iMessage
$bobjs)[iMessage]edgefloat kEFRightBottomThis allows: - Automatic resizing when window changes - Additional UI elements alongside message
Calculate iMessage as con(
'I am a message with CRs in it ',
kcr,kcr,
' and ',
style(kesccolor,kblue),
' style commands'
)
No special handling required --- styles and CRs are handled by the sizing routine.
Run this: - On window open - Whenever iMessage changes
Set reference MessageRef to $cinst.$objs.MessagePane.$bobjs.iMessage
Calculate HeightRemainder as $cinst.$height-MessageRef.$height
Calculate NewHeight as tStringFields.$getWindowFieldHeightForAvailWidth(
MessageRef.$fieldstyle,
iMessage,
MessageRef.$width
)
If $root.$height<NewHeight
Breakpoint Uh oh! Message larger than screen
End If
Calculate NewHeight as NewHeight+HeightRemainder
If NewHeight<$cinst.$height
Calculate NewHeight as $cinst.$height
End If
$getWindowFieldHeightForAvailWidthThis is the real workhorse.
It: - Handles CRs - Handles wrapping - Strips style codes correctly - Accounts for bitmap width
Variable Default
bitmapWidth 18 bmpCount 0 height 0 linesToAdd 0 StyleSubString "" Token "" TokenString "" TokenWidth 0
Calculate Height as $cinst.$getWindowFieldHeight(pFieldStyle)
Calculate LinesToAdd as 0
Calculate bitmapWidth as 18
Calculate TokenString as pText
While pos(chr(27),TokenString)>0
Calculate styleSubString as mid(TokenString,pos(chr(27),TokenString))
Calculate styleSubString as mid(styleSubString,1,pos(chr(35),styleSubString))
If asc(styleSubString,2)=kEscBmp
Calculate bmpCount as bmpCount+$cinst.$replace(TokenString,styleSubString,'',TokenString)
Else
Calculate TokenString as replaceall(TokenString,styleSubString,'')
End If
End While
Calculate Token as strtok(nam(TokenString),kCr)
While len(TokenString)>0|len(Token)>0
If len(Token)=0
Calculate LinesToAdd as LinesToAdd+1
Else
Calculate TokenWidth as $cinst.$getWindowFieldWidth(pFieldStyle,Token)+bmpCount*bitmapWidth
Calculate LinesToAdd as LinesToAdd+int(TokenWidth/pAvailWidth)+1
End If
Calculate Token as strtok(nam(TokenString),kCr)
End While
Quit method Height*LinesToAdd
kEscBmp) are counted and given widthSimpler but less accurate:
Calculate pixWidth as FontOps.$wintextwidth(cMessage,'Chicago',12)
Calculate pixHeight as FontOps.$wintextheight('Chicago',12)
Calculate wrapWidth as msgFld.$width-20
Do msgFld.$height.$assign(
((pixHeight+4)*(int(pixWidth/wrapWidth)+2+crCount))
+((pixHeight/2)*(crCount=0))
)
This method:
In short:
Set it up once, and let Omnis behave properly.