Greying out controls *and* labels with a checkbox

I have a preferences pane inside a tab panel. Inside this pane is a set of controls that should only be enabled if you explicitly check a checkbox at the top. I want them to be visible, but greyed out, until the checkbox is checked.

Using groupbox.enabled, I can enable/disable the controls, but they always appear normally.
With groupbox.visible, I can hide/show the controls, but then you can’t see them until you click the box.

I can sort of simulate this using the checkbox .enabled and .transparent properties in the checkbox’s Action event, but then all the labels for the controls remain black, they don’t grey out with the controls themselves:

if me.Value = True then
  gbEEPROMSettings.Transparent = false
  gbEEPROMSettings.enabled = true
else 
  gbEEPROMSettings.Transparent = True
  gbEEPROMSettings.Enabled = false
end if

This is what the window looks like when it’s “greyed out”:

and this is what it looks like when the “change EEPROM Settings” button is checked:

Aren’t all the controls in a GroupBox children of the groupbox? I would think that setting the transparency for the box would set it for all children as well, no?

The Transparent property determines whether the control has a transparent backing on Windows.

Determines whether the control is transparent on Windows. The default is False. Has no effect on macOS or Linux.

I assume you’re actually looking for the Visible property?

Determines whether the control is transparent on Windows. The default is False. Has no effect on macOS or Linux.

[EDIT upon further testing]: So the transparency seems to have no effect on mac, but enable/disable does. If I enable the groupbox, then the controls are normal. If I disable it, the controls are grey. But the labels are always black. I want those to go grey as well. Is the only way to do that to manually change the text color of all the labels?

I don’t want Visible, because that makes the groupBox disappear entirely. I want the controls and labels to be visible, but greyed out, Ideally without having to manually set that property for each control, one at a time:

Setting Enabled to False should cause fields to display their disabled state. That’s the only difference I see in the first set of images. The first image has the following to disable everything in the GroupBox:

gbEEPROMSettings.Enabled = false

While it looks like the second image has the equivalent of this, which enables those fields with their individual Enabled property set to True, but those with their Enabled property set to False are still disabled:

gbEEPROMSettings.Enabled = false
fldIP.Enabled = True
fldPort.Enabled = False
...etc.

Unless I’m missing something. I haven’t had my coffee yet.

you’re correct - I edited my post above.

Enabling does what I want for the controls but not for the labels, which are still their normal intensity. I want the whole groupbox to go grey when it’s disabled

Ah, yeah, labels are decorators and don’t have a visual disabled state. In the case of labels, it’s a functional change when you set Enabled to False. It disables events rather than displaying the label differently. This is the expected behavior. If you want the label text to display a disabled state, you’d have to set the TextColor property:

myDisabledLabel.TextColor = Color.Gray '// Or, whatever color makes the most sense in your UI

that’s what I was afraid of. There’s no way to do that for all the text labels in the groupbox is there?

Sure. You could iterate over the children of the GroupBox. I wrote this function that will automatically recolor any direct child labels of whatever control you pass as a parameter if their Enabled property is False. You could easily remove the Enabled check if you just want them all recolored.

Private Sub setLabelsDisabled(withParent as DesktopUIControl)
  var currentLabel as DesktopLabel
  for each c as DesktopUIControl in self.Controls
    if c isa DesktopLabel and c.Parent = withParent then
      currentLabel = DesktopLabel( c )
      if c.Enabled = False Then
        currentLabel.TextColor = Color.Gray '// Probably not what you want to use in production. See ColorGroup or ColorGroup.NamedColor
      else
        currentLabel.TextColor = Color.Black '// Probably not what you want to use in production. See ColorGroup or ColorGroup.NamedColor
      end if
    end if
  next c
End Sub

Called as:

setLabelsDisabled( GroupBox1 )

thanks. I’ll give that a try. This is a relatively simple example for this app, but there will be other areas where entire sections of the UI need to be grey until things like proper connections to the MCU are established, so this will come in handy!

Happy to help.

Here’s a version that you can throw in a module to make it available everywhere:

Public Sub setLabelsState(extends onParent as DesktopUIControl)
  var currentLabel as DesktopLabel
  for each c as DesktopUIControl in onParent.Window.Controls
    if c isa DesktopLabel and c.Parent = onParent then
      currentLabel = DesktopLabel( c )
      if c.Enabled = False then
        currentLabel.TextColor = Color.Gray
      else
        currentLabel.TextColor = Color.Black
      end if
    end if
  next c
End Sub

Call as:

GroupBox1.setLabelsState

even better!

I just tried it and realized it won’t work in 2021R2.1. I haven’t upgraded to r3 yet (don’t usually like doing that kind of thing mid-project). I guess maybe I should. It’s probably worth it for something like this.

No need to upgrade just for this. Give me a minute to fire up 2021r2.1 and I’ll modify the code.

Desktop API 1.0 compatible method:

Public Sub setLabelsState(extends onParent as RectControl)
  var currentLabel as Label
  for each c as RectControl in onParent.Window.Controls
    if c isa Label and c.Parent = onParent then
      currentLabel = Label( c )
      if c.Enabled = False then
        currentLabel.TextColor = Color.Gray
      else
        currentLabel.TextColor = Color.Black
      end if
    end if
  next c
End Sub

Be sure that you’re using ColorGroups so that your newly set colors are adaptive based on the user’s chosen theme.

3 Likes

Amazing. thanks. That works great!

1 Like

Well you could (maybe should) use a containerControl as a Form, you could enable/disable that with all its controls on int my simply enabled = False/True on the container.

Plus you can color the background just as if it was a groupbox.

That won’t paint the labels with a disabled state.

So I modified @Anthony_G_Cyphers’ code slightly. What I do now is set the default state for all the labels to Disabled and the default text color to gray. The parent groupbox is also disabled, which greys the controls. it looks like this when you load it up:

The method now toggles both the color and the state of the labels:

Sub ToggleLabelsColorByState(extends onParent as RectControl)
  var currentLabel as Label
  for each c as RectControl in onParent.Window.Controls
    if c isa Label and c.Parent = onParent then
      currentLabel = Label( c )
      if c.Enabled = False then
        currentLabel.Enabled = true
        currentLabel.TextColor = Color.Black
      else
        currentLabel.Enabled = false
        currentLabel.TextColor = Color.Gray
      end if
    end if
  next c
End Sub

When you check the box at the top you get this, which is what I’m after:

2 Likes

Then that’s a bug…

Happy to be proven wrong, but as far as I know it’s the expected behavior for labels that the functionality be modified when disabled without changing the display of the control as it’s a decorator.