How to create a frame for texts?

Example object for this post can be downloaded here.

To frame the displayed texts the maximal vertical and horizontal sizes of the texts are needed to be known. These values depend on the content and alignment of the texts.

In the following example a frame is created for the texts displayed in the How to make integer alignment for texts? post. This example also covers the left aligned and the right aligned value columns. If the value column is aligned by the integer parts of the values, the decimal points and the fractions after it are positioned in the middle of the width of the block. In case of left alignment the starting position of the column value is in the middle of the width of the block, right alignment aligns the value column to the end of the width of the block.

TipsAndTricks_FrameTexts_Ex1

! ------------------------------------------------------------------------------
! Input parameters controlled by the user:
! ------------------------------------------------------------------------------
! ZZYZX 		- (Length) height of the block whose data are displayed
! blockWidth 		- (Length) width of the block whose data are displayed
! blockDepth 		- (Length) depth of the block whose data are displayed
! sampleSize 		- (RealNum) indicates the height of the font from the
! 		 	  baseline to the cap height, given in Paper size - mm
! fontType 		- (String) font family of the displayed text
! stSepChar  		- (String) the actual decimal point character, 
! 		 	  depends on the settings of the operation system
! iValueAlign		- (Integer) Type of alignment of the value column:
!		 	  1 - Right Align, 2 - Left Align, 3 - Integer Align
! bFramedText		- (Boolean) Displaying frame for the texts
! framePen		- (Pen) Pen colour of the frame  
! stAreaName 		- (String) the name of the block area value
! stVolumeName 		- (String) the name of the block volume value
! stWidthName 		- (String) the name of the block width value
! stDepthName 		- (String) the name of the block depth value
! stHeightName 		- (String) the name of the block height value

! ------------------------------------------------------------------------------
! Draw the block in 2D
! ------------------------------------------------------------------------------
rect2 0, 0, blockWidth, blockDepth

! ------------------------------------------------------------------------------
! Define styles
! ------------------------------------------------------------------------------
! Not all of the following variables are used in this example, but the kind of
! definition showed below is the GRAPHISOFT standard constant definition

! Text styles
NORMAL		= 0
BOLD 		= 1
ITALIC 		= 2
UNDERLINE 	= 4

! Anchor positions
LEFT_UPPER	= 1
MIDDLE_UPPER	= 2
RIGHT_UPPER	= 3
LEFT_MIDDLE	= 4
MIDDLE		= 5
RIGHT_MIDDLE	= 6
LEFT_LOWER	= 7
MIDDLE_LOWER	= 8
RIGHT_LOWER	= 9
 
! Define the different text styles
define style "ItalicStyle" 	fontType, sampleSize, LEFT_UPPER, ITALIC
define style "NormalLeftStyle" 	fontType, sampleSize, LEFT_UPPER, NORMAL
define style "NormalRightStyle" fontType, sampleSize, RIGHT_UPPER, NORMAL

! ------------------------------------------------------------------------------
! Set input data for the text drawing
! ------------------------------------------------------------------------------

! Set the multiplier of the paper scale
PAPER_TO_MODEL = GLOB_SCALE / 1000

! Set text coordinate variable:
! samplesize is given in Paper Size - mm, convert it into Model size  - m
! calculate the row height from it, 
! therefore the row height will not depend on the font family
dy = - sampleSize * 1.5 * PAPER_TO_MODEL                                

! ------------------------------------------------------------------------------
! Display the texts in the first column
! ------------------------------------------------------------------------------
style "ItalicStyle"			! Set the previously defined style

text2 0, 0, 	stAreaName
text2 0, dy, 	stVolumeName

style "NormalLeftStyle"			! Set the previously defined style

text2 0, dy * 2, stWidthName
text2 0, dy * 3, stDepthName
text2 0, dy * 4, stHeightName

! ------------------------------------------------------------------------------
! Use str command to get the values to display as a string
! ------------------------------------------------------------------------------
_format = "%~.2m"	! Unit: meter, Decimals: 2, Hide zero decimals
_stAreaValue = ""
_stAreaValue = str(_format, _areaValue)

_stVolumeValue = ""
_stVolumeValue = str(_format, _volumeValue)

_stWidthValue = ""
_stWidthValue = str(_format, blockWidth)

_stDepthValue = ""
_stDepthValue = str(_format, blockDepth)

_stHeightValue = ""
_stHeightValue = str(_format, ZZYZX)

! ------------------------------------------------------------------------------
! Set the x coordinates for the texts in the second column
! ------------------------------------------------------------------------------
if iValueAlign = 1 then				! Right Alignment
    style "NormalRightStyle"
    _xPosArea 	= blockWidth
    _xPosVolume = blockWidth
    _xPosWidth 	= blockWidth
    _xPosDepth 	= blockWidth
    _xPosHeight = blockWidth
else
    if iValueAlign = 2 then			! Left Alignment
        style "NormalLeftStyle"
        _xPosArea 	= blockWidth / 2
        _xPosVolume 	= blockWidth / 2
        _xPosWidth 	= blockWidth / 2
        _xPosDepth 	= blockWidth / 2
        _xPosHeight 	= blockWidth / 2
    else					! Integer Alignment
        ! ----------------------------------------------------------------------
        ! Area Value
        ! ----------------------------------------------------------------------
        ! Get the integer position of the decimal point
        _posSep = strstr(_stAreaValue, stSepChar)    
        ! If the decimal point is not found, 
        ! get the width of the whole string
        if _posSep = 0 then                                                        
            _lengthOfIntegerPart = stw (_stAreaValue)    
        ! If the decimal point is found, 
        ! get the width of the integer part substring                        
        else
            _lengthOfIntegerPart = stw (strsub (_stAreaValue, 0, _posSep - 1)) 
        endif
        ! Convert the length of the integer part substring
        !  into Model size - m, intend the string position with it
        _xPosArea    = blockWidth / 2 - _lengthOfIntegerPart * PAPER_TO_MODEL 

        ! ----------------------------------------------------------------------
        ! Volume Value
        ! ----------------------------------------------------------------------
        _posSep = strstr(_stVolumeValue, stSepChar)
        if _posSep = 0 then
            _lengthOfIntegerPart = stw (_stVolumeValue)
        else
            _lengthOfIntegerPart = stw (strsub (_stVolumeValue, 0, _posSep - 1))
        endif
        _xPosVolume    = blockWidth / 2 - _lengthOfIntegerPart * PAPER_TO_MODEL

        ! ----------------------------------------------------------------------
        ! Width Value
        ! ----------------------------------------------------------------------
        _posSep = strstr(_stWidthValue, stSepChar)
        if _posSep = 0 then
            _lengthOfIntegerPart = stw (_stWidthValue)
        else
            _lengthOfIntegerPart = stw (strsub (_stWidthValue, 0, _posSep - 1))
        endif
        _xPosWidth    = blockWidth / 2 - _lengthOfIntegerPart * PAPER_TO_MODEL

        ! ----------------------------------------------------------------------
        ! Depth Value
        ! ----------------------------------------------------------------------
        _posSep = strstr(_stDepthValue, stSepChar)
        if _posSep = 0 then
            _lengthOfIntegerPart = stw (_stDepthValue)
        else
            _lengthOfIntegerPart = stw (strsub (_stDepthValue, 0, _posSep - 1))
        endif
        _xPosDepth    = blockWidth / 2 - _lengthOfIntegerPart * PAPER_TO_MODEL

        ! ----------------------------------------------------------------------
        ! Height Value
        ! ----------------------------------------------------------------------
        _posSep = strstr(_stHeightValue, stSepChar)
        if _posSep = 0 then
            _lengthOfIntegerPart = stw (_stHeightValue)
        else
            _lengthOfIntegerPart = stw (strsub (_stHeightValue, 0, _posSep - 1))
        endif
        _xPosHeight    = blockWidth / 2 - _lengthOfIntegerPart * PAPER_TO_MODEL
    endif
endif
! ------------------------------------------------------------------------------
! Display the texts in the second column
! ------------------------------------------------------------------------------
style "NormalLeftStyle"			! Set the previously defined style

text2 _xPosArea, 	0, 	_stAreaValue
text2 _xPosVolume, 	dy, 	_stVolumeValue
text2 _xPosWidth, 	dy * 2, _stWidthValue
text2 _xPosDepth, 	dy * 3, _stDepthValue
text2 _xPosHeight, 	dy * 4, _stHeightValue

In order to get the maximal vertical and horizontal sizes of the displayed texts, the displayed text values are needed to be string types. In the following example the alignment of the texts is controlled by the user by the “iValueAlign” parameter. In case of right alignment the maximal width of the displayed texts is equal to the width of the block. In case of left alignment the maximum length of the displayed texts in the value column gives the position of the right frame. The STW function returns the length of the displayed text values in millimeters (Paper size). The horizontal position of the right frame is calculated from the middle of the block (blockWidth / 2), by adding the length of the longest displayed text in model size. (The ‘\’ characters in the example below are only used for line breaking.)

In case of integer alignment the horizontal position of the right frame depends on the maximal length of the fractional part of the displayed values. For getting the location of the decimal point, the STRSTR function is used. It returns an integer number, which indicates the position of the decimal point among the characters within the string value. The STRLEN function returns an integer number which gives the position of the last character in the displayed text. The STRSUB function is used for getting the part of the string from the decimal point to the end of the displayed text. In this example the decimal point is included in the horizontal positioning of the right frame. The STW function returns the length of the substring in millimeters (paper size). The horizontal position of the right frame is calculated from the middle of the block (blockWidth / 2), by adding the length of the longest fractional part (including the decimal point) of the displayed text in model size.

TipsAndTricks_FrameTexts_Ex2

For the bottom line of the frame the actual text style height, which depends on the font family set by the user, is requested by the “Height_of_style” request. This request returns the total height of the style in millimeters (paper size), so it have to be converted into model size for drawing the frame. The dy variable do not depends on the font family in this example, but the last text row height is calculated from this request. Therefore the bottom frame’s horizontal position changes when the user switches between font families, but the displayed texts’s positions do not.

! ------------------------------------------------------------------------------
! Frame the displayed text
! ------------------------------------------------------------------------------
if bFramedText then
    pen framePen
    if iValueAlign = 1 then            			! Right Alignment
        _textWidth = blockWidth
    else
        if iValueAlign = 2 then        			! Left Alignment
            _textWidth = max(stw(_stAreaValue), stw(_stVolumeValue),\
                             stw(_stWidthValue), stw(_stDepthValue),\
                             stw(_stHeightValue)) *\
                         PAPER_TO_MODEL + blockWidth / 2
        else                           			! Integer Alignment
            _stRealPartArea = strsub (_stAreaValue,\
                              strstr(_stAreaValue, stSepChar),\
                              strlen(_stAreaValue))
            _stRealPartVolume = strsub (_stVolumeValue,\ 
                                strstr(_stVolumeValue, stSepChar),\ 
                                strlen(_stVolumeValue))
            _stRealPartWidth = strsub (_stWidthValue,\
                               strstr(_stWidthValue, stSepChar),\
                               strlen(_stWidthValue))
            _stRealPartDepth = strsub (_stDepthValue,\
                               strstr(_stDepthValue, stSepChar),\
                               strlen(_stDepthValue))
            _stRealPartHeight = strsub (_stHeightValue,\
                                strstr(_stHeightValue, stSepChar),\
                                strlen(_stHeightValue))

            _textWidth = max(stw(_stRealPartArea), stw(_stRealPartVolume), \
                             stw(_stRealPartWidth), stw(_stRealPartDepth), \
                             stw(_stRealPartHeight)) * \
                         PAPER_TO_MODEL + blockWidth / 2
        endif
    endif

    ! Get the height of the actual text style, which is 
    ! the exact height of the last row in Paper size - mm 
    r = request ("Height_of_style", "NormalLeftStyle", _textSize) 

    ! Draw the frame with the calculated width and height
    rect2 0, 0, _textWidth, dy * 4 -(_textSize * PAPER_TO_MODEL)
endif

Command and function pool:
RECT2
DEFINE STYLE
GLOB_SCALE
[SET] STYLE
TEXT2
STR
STRSTR
STW
STRSUB
MAX
STRLEN
“Height_of_style”