Autofit a .NET label by height with support for tab characters


#1

I’m trying to get a .NET label to autofit its contents and then in turn change the size of the dialog. Much like how messagebox behaves only with this I have more control over the width of the message box and more importantly for me the position of the message box. Center screen doesn’t really work that great because the UI of my script will more often than not get used on a secondary monitor.

Tabs \t doesn’t work either. At least I can’t see a way to get them to.

Here’s the code:

clearlistener()
(
  try destroyDialog rolloutName catch()

  ::rolloutName

  fn dnDrawingColorFromColorMan name = (clr = (colorMan.getColor name) * 255.0 ; (dotNetClass "System.Drawing.Color").fromARGB clr.x clr.y clr.z)
  fn dnDrawingSize x y               = dotnetObject "System.Drawing.Size" x y

  rollout rolloutName "A Label Attempt to Change the Rollout Size" (

   dotNetControl lbl_msg "Label"

   fn dotNetControlsInt =
   (

    -- show lbl_msg

    labelMaxWidth = rolloutName.width-20
    labelMinWidth = 200
    p2ScreenSize = [(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.width,(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.height]
    theFont = dotnetobject "System.Drawing.Font" "Arial" 10

    -- Label colours and others

    lbl_msg.font                       = theFont
    lbl_msg.BackColor                  = dnDrawingColorFromColorMan #background
    lbl_msg.ForeColor                  = dnDrawingColorFromColorMan #text
    lbl_msg.UseCompatibleTextRendering = true

    -- Here's where I've tried to get the label to autofit

    lbl_msg.AutoSize    = true
    lbl_msg.MinimumSize = dnDrawingSize labelMinWidth 200
    lbl_msg.MaximumSize = dnDrawingSize labelMaxWidth (p2ScreenSize.y-80) -- Minus 80 for the taskbar as it could be double height. 40 px is what's on mine for a single height taskbar
    lbl_msg.Height      = lbl_msg.PreferredHeight
    lbl_msg.AutoSize    = true

    labelText = "I'm\ttrying to access a property of the mainSubRollout for the order the sub rollouts are in."
    labelText += "\n"
    labelText += "\n\tAfter running the code below and dragging Sub 2 rollout to the top like the image and checking mainRolTest.mainSubRollout.rollouts it always returns #(Rollout:subRollout1, Rollout:subRollout2) even though the displayed order of the rollouts are not the same."
    labelText += "\n"
    labelText += "\n\tenter image description here"
    labelText += "\n"
    labelText += "\n\tHow can I access this order in which they are currently displayed?"
    labelText += "\n"
    labelText += "\n\tA result for the image should be: #(Rollout:subRollout2, Rollout:subRollout1)"
    labelText += "\n"
    labelText += "\n\tI have a Panel that I'm creating programmatically; additionally I'm adding several components to it."
    labelText += "\n"
    labelText += "\n\tOne of these components is a Label which will contain user-generated content."
    labelText += "\n"
    labelText += "\n\tI don't know how tall the label should be, but it does have a fixed width."
    labelText += "\n"
    labelText += "\n\tHow can I set the height so that it displays all the text, without changing the width?"

    -- Not a great attempt at getting tabs '\t' to work

    lbl_msg.TabIndex = 4
    lbl_msg.TabStop = true
    -- lbl_msg.Text = substituteString labelText "\t" "\x0009" -- A Unicode attempt.
    -- lbl_msg.Text = substituteString labelText "\t" "    " -- A Unicode attempt.

    lbl_msg.Text = labelText

    )

   on rolloutName open do dotNetControlsInt()

   )

  createDialog rolloutName 600 250

  )

22%20(15-00-03)


#2

According to this SO thread they don’t have to. But you could replace them with spaces, no?
%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5

clearlistener()
(
  try destroyDialog rolloutName catch()

  ::rolloutName

  fn dnDrawingColorFromColorMan name = (clr = (colorMan.getColor name) * 255.0 ; (dotNetClass "System.Drawing.Color").fromARGB clr.x clr.y clr.z)
  fn dnDrawingSize x y               = dotnetObject "System.Drawing.Size" x y

  rollout rolloutName "A Label Attempt to Change the Rollout Size" (

   dotNetControl lbl_msg "Label"

   fn dotNetControlsInt =
   (

    -- show lbl_msg

    labelMaxWidth = rolloutName.width-20
    labelMinWidth = 200
    p2ScreenSize = [(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.width,(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.height]
    theFont = dotnetobject "System.Drawing.Font" "Arial" 10

    -- Label colours and others

    lbl_msg.font                       = theFont
    lbl_msg.BackColor                  = dnDrawingColorFromColorMan #background
    lbl_msg.ForeColor                  = dnDrawingColorFromColorMan #text
    lbl_msg.UseCompatibleTextRendering = true

    -- Here's where I've tried to get the label to autofit

    lbl_msg.AutoSize    = true
    lbl_msg.MinimumSize = dnDrawingSize labelMinWidth 200
    lbl_msg.MaximumSize = dnDrawingSize labelMaxWidth (p2ScreenSize.y-80) -- Minus 80 for the taskbar as it could be double height. 40 px is what's on mine for a single height taskbar
    lbl_msg.Height      = lbl_msg.PreferredHeight
    lbl_msg.AutoSize    = true

    labelText = "I'm{0}trying to access a property of the mainSubRollout for the order the sub rollouts are in."
    labelText += "\n"
    labelText += "\n{0}After running the code below and dragging Sub 2 rollout to the top like the image and checking mainRolTest.mainSubRollout.rollouts it always returns #(Rollout:subRollout1, Rollout:subRollout2) even though the displayed order of the rollouts are not the same."
    labelText += "\n"
    labelText += "\n{0}enter image description here"
    labelText += "\n"
    labelText += "\n{0}How can I access this order in which they are currently displayed?"
    labelText += "\n"
    labelText += "\n{0}A result for the image should be: #(Rollout:subRollout2, Rollout:subRollout1)"
    labelText += "\n"
    labelText += "\n{0}I have a Panel that I'm creating programmatically; additionally I'm adding several components to it."
    labelText += "\n"
    labelText += "\n{0}One of these components is a Label which will contain user-generated content."
    labelText += "\n"
    labelText += "\n{0}I don't know how tall the label should be, but it does have a fixed width."
    labelText += "\n"
    labelText += "\n{0}How can I set the height so that it displays all the text, without changing the width?"

    -- Not a great attempt at getting tabs '\t' to work

    lbl_msg.TabIndex = 4
    lbl_msg.TabStop = true
--     lbl_msg.Text = substituteString labelText "\t" "\x0009" -- A Unicode attempt.
--     lbl_msg.Text = substituteString labelText "\t" "    " -- A Unicode attempt.

	lbl_msg.Text = ( dotNetClass "system.string" ).format labelText ( dotNet.ValueToDotNetObject #("    ") ( dotnetclass "system.object[]" ) )
--     lbl_msg.Text = labelText

    )

   on rolloutName open do dotNetControlsInt()

   )

  createDialog rolloutName 600 250

  )

#3

As you can see it doesn’t line up.
image

I had tried doing that with what I had commented out in the code.

lbl_msg.Text = substituteString labelText "\t" "    "

I’ve switched over to a TextBox instead. It looks like a label at first glance but it has a vertical scroll bar, supports tabs characters.

The only issue I have is to get the main UI to resize based on the textbox size like how messagebox behaves. I’ve tried to access the height of the full scrollable text box but I cannot seem to get that value they all but one return 200. Here are the ones that I tried.

print lbl_msg.Bounds.Height           -- Returns: 200
print lbl_msg.ClientRectangle.Height  -- Returns: 200
print lbl_msg.ClientSize.Height       -- Returns: 200
print lbl_msg.DisplayRectangle.Height -- Returns: 200
print lbl_msg.MaximumSize.Height      -- Returns: 2080
print lbl_msg.MinimumSize.Height      -- Returns: 200
print lbl_msg.PreferredSize.Height    -- Returns: 200
print lbl_msg.Size.Height             -- Returns: 200

Here’s the UI
image

The code

(
  try destroyDialog rolloutName catch()

  ::rolloutName

  fn dnDrawingColorFromColorMan name = (clr = (colorMan.getColor name) * 255.0 ; (dotNetClass "System.Drawing.Color").fromARGB clr.x clr.y clr.z)
  fn dnDrawingSize x y               = dotnetObject "System.Drawing.Size" x y

  rollout rolloutName "A TextBox Attempt to Change the Rollout Size" (

    dotNetControl tb_msg "TextBox" pos:[10,0]

    fn dotNetControlsInt =
    (

      p2ScreenSize   = [(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.width,(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.height]
      textboxMaxWidth  = rolloutName.width-1
      textboxMaxHeight = (p2ScreenSize.y-80)
      textboxMinWidth  = 200
      textboxMinHeight = 200

      -- Props relating to the sizing of the text box
      tb_msg.AutoSize    = true
      tb_msg.Height      = tb_msg.PreferredHeight
      tb_msg.MaximumSize = dnDrawingSize textboxMaxWidth textboxMaxHeight -- Minus 80 for the taskbar as it could be double height. 40 px is what's on mine for a single height taskbar
      tb_msg.MinimumSize = dnDrawingSize textboxMinWidth textboxMinHeight
      tb_msg.Multiline   = true
      tb_msg.WordWrap    = true -- No need for horizontal scrollbars when this is enabled

      -- Other properties for the textbox
      tb_msg.BackColor   = dnDrawingColorFromColorMan #background
      tb_msg.BorderStyle = none
      tb_msg.Font        = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11.5 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
      tb_msg.ForeColor   = dnDrawingColorFromColorMan #text
      tb_msg.ReadOnly    = true
      tb_msg.ScrollBars  = (dotNetClass "System.Windows.Forms.ScrollBars").Vertical
      tb_msg.Width       = rolloutName.width-10

      -- Here's where I've tried to get the textboxs full height in the scrollable area
      print tb_msg.Bounds.Height           -- Returns: 200
      print tb_msg.ClientRectangle.Height  -- Returns: 200
      print tb_msg.ClientSize.Height       -- Returns: 200
      print tb_msg.DisplayRectangle.Height -- Returns: 200
      print tb_msg.MaximumSize.Height      -- Returns: 2080
      print tb_msg.MinimumSize.Height      -- Returns: 200
      print tb_msg.PreferredSize.Height    -- Returns: 200
      print tb_msg.Size.Height             -- Returns: 200

      textboxText = "\r\nI'm\ttrying to access a property of the mainSubRollout for the order the sub rollouts are in."
      textboxText += "\r\n\r\nI\t{0}{0}try"
      textboxText += "\r\n{0}After running the code below and dragging Sub 2 rollout to the top like the image and checking mainRolTest.mainSubRollout.rollouts it always returns #(Rollout:subRollout1, Rollout:subRollout2) even though the displayed order of the rollouts are not the same."
      textboxText += "\r\n"
      textboxText += "\r\n{0}enter image description here"
      textboxText += "\r\n"
      textboxText += "\r\n{0}How can I access this order in which they are currently displayed?"
      textboxText += "\r\n"
      textboxText += "\r\n{0}A result for the image should be: #(Rollout:subRollout2, Rollout:subRollout1)"
      textboxText += "\r\n"
      textboxText += "\r\n{0}I have a Panel that I'm creating programmatically; additionally I'm adding several components to it."
      textboxText += "\r\n"
      textboxText += "\r\n{0}One of these components is a textbox which will contain user-generated content."
      textboxText += "\r\n"
      textboxText += "\r\n{0}I don't know how tall the textbox should be, but it does have a fixed width."
      textboxText += "\r\n"
      textboxText += "\r\n{0}How can I set the height so that it displays all the text, without changing the width?"

      tb_msg.text = textboxText

      )

    on rolloutName open do dotNetControlsInt()

    )

  createDialog rolloutName 600 250

  )

#4

I’ve added a getMessageHeight() function that will make the text box the correct height (so long as there’s not to many lines that have overflowed and wrapped down.

This will do for now I suppose.

image

It looks more like a label without the scrollbars and looks better. You can still select the text but that’s no issue for me. Users can select it and copy it if it contains some info they might like.

clearlistener()
(
  try destroyDialog rolloutName catch()

  ::rolloutName

  fn getMessageHeight msg            = (height = 19 * (filterString msg "\n" splitEmptyTokens:true).count ; if height < 20 then height = 20 else height)
  fn dnDrawingColorFromColorMan name = (clr = (colorMan.getColor name) * 255.0 ; (dotNetClass "System.Drawing.Color").fromARGB clr.x clr.y clr.z)
  fn dnDrawingSize x y               = dotnetObject "System.Drawing.Size" x y

  rollout rolloutName "A TextBox Attempt to Change the Rollout Size" (

    dotNetControl tb_msg "TextBox" pos:[10,10]
    button btn_copy_to_clipboard "Copy to Clipboard" width:105 height:22 tooltip:"Copies the message to the clipboard."

    fn dotNetControlsInt =
    (

      p2ScreenSize      = [(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.width,(dotnetclass"System.Windows.Forms.Screen").primaryscreen.bounds.height]
      textboxMaxWidth   = rolloutName.width-1
      textboxMaxHeight  = p2ScreenSize.y-80
      textboxMinWidth   = 200
      textboxMinHeight  = 50
      paddingTextboxBtm = 25
      gutterBottom      = 50
      buttonPadding     = 10

      -- Props relating to the sizing of the text box
      tb_msg.AutoSize    = true
      tb_msg.Height      = tb_msg.PreferredHeight
      tb_msg.MaximumSize = dnDrawingSize textboxMaxWidth textboxMaxHeight -- Minus 80 for the taskbar as it could be double height. 40 px is what's on mine for a single height taskbar
      tb_msg.MinimumSize = dnDrawingSize textboxMinWidth textboxMinHeight
      tb_msg.Multiline   = true
      tb_msg.WordWrap    = true -- No need for horizontal scrollbars when this is true and it doesn't have an affect anyway

      -- Other properties for the textbox
      tb_msg.BackColor   = dnDrawingColorFromColorMan #background
      tb_msg.BorderStyle = none
      tb_msg.Font        = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 11.5 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
      tb_msg.ForeColor   = dnDrawingColorFromColorMan #text
      tb_msg.ReadOnly    = true
      tb_msg.Width       = rolloutName.width-10

      textboxText = "\r\nI'm\ttrying to access a property of the mainSubRollout for the order the sub rollouts are in."
      textboxText += "\r\n\r\nI\t{0}{0}try"
      textboxText += "\r\n{0}After running the code below and dragging Sub 2 rollout to the top like the image and checking mainRolTest.mainSubRollout.rollouts it always returns #(Rollout:subRollout1, Rollout:subRollout2) even though the displayed order of the rollouts are not the same."
      textboxText += "\r\n"
      textboxText += "\r\n{0}enter image description here"
      textboxText += "\r\n"
      textboxText += "\r\n{0}How can I access this order in which they are currently displayed?"
      textboxText += "\r\n"
      textboxText += "\r\n{0}A result for the image should be: #(Rollout:subRollout2, Rollout:subRollout1)"
      textboxText += "\r\n"
      textboxText += "\r\n{0}I have a Panel that I'm creating programmatically; additionally I'm adding several components to it."
      textboxText += "\r\n"
      textboxText += "\r\n{0}One of these components is a textbox which will contain user-generated content."
      textboxText += "\r\n"
      textboxText += "\r\n{0}I don't know how tall the textbox should be, but it does have a fixed width."
      textboxText += "\r\n"
      textboxText += "\r\n{0}How can I set the height so that it displays all the text, without changing the width?"

      -- Short example
      textboxText = "\r\nIn\t\tthis line it shows how the tab character is now working and that the main rollout is resized to suit.\r\n\r\nHere's another\tline."

      -- Set the text box height and the height of the dialog based on the getMessageHeight function
      tb_msg.Height = getMessageHeight textboxText + paddingTextboxBtm -- paddingTextboxBtm is some additional padding
      SetDialogSize rolloutName [(GetDialogSize rolloutName).x,tb_msg.height+gutterBottom]

      btn_copy_to_clipboard.pos = [buttonPadding,(GetDialogSize rolloutName).y-btn_copy_to_clipboard.height-buttonPadding]

      if tb_msg.Height > textboxMaxHeight do tb_msg.ScrollBars = (dotNetClass "System.Windows.Forms.ScrollBars").Vertical

      tb_msg.text = textboxText

      )

    on btn_copy_to_clipboard pressed do ((dotNetClass "System.Windows.Forms.Clipboard").setText(tb_msg.text) ; btn_copy_to_clipboard.enabled = false)
    on rolloutName open              do dotNetControlsInt()

    )

createDialog rolloutName 500 250

)