nested Controls - enabled flag doesn't change ?

In the project file attached I have a simple Canvas and three radio buttons put in as child.

if I set the parent (Canvas) to enabled = false the radio buttons turn grey (=disabled) - Ok. However the enabled
flag of each radio button is still true.

I am wondering if this is a bug since the parent also disables all child controls and you can’t determine the control enabled flag
for instance of work with subclasses ect. So I don’t think this makes sense does it ?

https://www.dropbox.com/s/f7jiyatrvqnx0yc/nested_controls_enable_disable.xojo_binary_project?dl=0

Hmm damn. I think the documentation mentions this but still I don’t the idea behind.

Think of a Canvas as a container, just like a Window or a ContainerControl. When you make a container invisible, everything contained into it becomes invisible. No need for each individual child to have its visible property set. The same applies to enabled.

Well but if you use for instance subclassed Canvases or ContainerControls and you need to check for
Enabled flag your are *****. I have a lot of controls which responds to mouseEnter/Exit events and those still
fire although being disabled. In order to prevent this I wanted to check the enabled flag so my best solution is currently in a subclassed control to check for it’s parent enabled flag.

[code]Function parentEnabled(extends c as ContainerControl) As Boolean
if c.Parent=nil then
return c.Enabled
else
dim parentView as RectControl = c.Parent
while( parentView.Parent<>nil )
parentView = parentView.Parent
wend
return parentView.Enabled
end if

End Function

Function parentEnabled(extends r as RectControl) As Boolean
if r.Parent=nil then
return r.Enabled
else
dim parentView as RectControl = r.Parent
while( parentView.Parent<>nil )
parentView = parentView.Parent
wend
return parentView.Enabled
end if

End Function
[/code]

IMO the docs should say:

[quote=249455:@Eli Ott]IMO the docs should say:

Disabling a parent control visually disables all its child controls, but retains the previous visibility status of all children.[/quote]

Why don’t you submit a documentation bug report ? That sounds more precise, and I am sure Paul will look into it.

Well, the controls are disabled. They don’t respond to mouseDown so they’re disabled so to say but the flag enabled isn’t set for the child. This is kind of confusing as you don’t have a precise state when you go the way through the parent control.

I’ll check if the get the correct result from declares.

Edit:
Yep. The declares get the correct state. I can’t rely on the enabled state of the xojo Control.

[quote]Function isEnabled(extends r as RectControl) As Boolean
declare function isEnabled lib “Cocoa” Selector “isEnabled” (obj as integer) as Boolean
return isEnabled(r.Handle)
End Function[/quote]

[code]Declare Function isEnabled Lib “Cocoa” Selector “isEnabled” (NSControl As Ptr) As Boolean

Canvas1.Enabled = False

Dim b1 As Boolean = RadioButton1.Enabled
Dim b2 As Boolean = isEnabled(Ptr(RadioButton1.Handle))[/code]
… where Canvas1 is the parent of RadioButton1.

[quote=249462:@Eli Ott][code]Declare Function isEnabled Lib “Cocoa” Selector “isEnabled” (NSControl As Ptr) As Boolean

Canvas1.Enabled = False

Dim b1 As Boolean = RadioButton1.Enabled
Dim b2 As Boolean = isEnabled(Ptr(RadioButton1.Handle))[/code]
… where Canvas1 is the parent of RadioButton1.[/quote]

Well I thought I had a solution but nope. A Xojo canvas has no isEnabled method. So you have basically
nothing to exactly determine if the control is really enabled or not. Great stuff!

[quote] declare function isEnabled lib “Cocoa” Selector “isEnabled” (obj as integer) as Boolean
declare function respondsToSelector lib “Cocoa” Selector “respondsToSelector:” (obj as integer, functionName as CFStringRef) as Boolean
if respondsToSelector(r.Handle, “isEnabled”) then
return isEnabled(r.Handle)
else
break // bang!!!
end if[/quote]

So does anyone know how to check the enabled state of a RectControl correctly ?

You should maybe try the code and/or read it properly instead of ranting around: isEnabled is a declare into the Cocoa library (see the first line).

The code runs fine and shows that isEnabled returns False, while Xojo returns True on a RadioButton of which the parent is disabled. So Xojo is not returning the correct state. So IMHO this is a bug on OS X - don’t know about Windows and Linux.

[quote=249485:@Eli Ott]You should maybe try the code and/or read it properly instead of ranting around: isEnabled is a declare into the Cocoa library (see the first line).

The code runs fine and shows that isEnabled returns False, while Xojo returns True on a RadioButton of which the parent is disabled. So Xojo is not returning the correct state. So IMHO this is a bug on OS X - don’t know about Windows and Linux.[/quote]

I am not ranting. I am trying to find a solution for hours of work.

The declare runs fine for for some controls yes but not for a canvas/container control which I need to check.
Anyway, I don’t know where the bug comes from, OSX or Xojo or maybe it’s like it is by design. The bottom line is you
are not able to check reliably thestate of a control if the control didn’t modified the flag itself (=parent has modified it). Also in case
you check parent state and control state doesn’t warrant your current state is the correct one.

Some topics of in the feedback says disabling a Label doesn’t change the label to grey but that’s it.

After testing I come to the conclusion, that checking the parent’s control flag is the way. Before I was assuming:
parent.Enabled = false
parent.childXY = true

would enable the child again but it’s not true. So this works and Eli was right.

if me.parentEnabled and me.Enabled then //.. end if

[code]Function parentEnabled(extends c as ContainerControl) As Boolean
if c.Parent=nil then
return c.Enabled
else
dim parentView as RectControl = c.Parent
while( parentView.Parent<>nil )
parentView = parentView.Parent
wend
return parentView.Enabled
end if

End Function

Function parentEnabled(extends r as RectControl) As Boolean
if r.Parent=nil then
return r.Enabled
else
dim parentView as RectControl = r.Parent
while( parentView.Parent<>nil )
parentView = parentView.Parent
wend
return parentView.Enabled
end if

End Function[/code]

You can also use something simple like

Function RealEnabled(Extends R as RectControl) As Boolean if R.Parent <> nil then Return R.Enabled and R.Parent.Enabled else Return R.Enabled end if End Function

Note that this won’t work in case of “russian dolls stacking”, where there are several layers of parent and the enabled is far from R. It would require a recursive method.

From your OP the issue was that the radio buttons inside a canvas / container control would not show the correct enabling state.

I showed you that this works by checking with the isEnabled declare. This works reliable for all native controls (which means not for listboxes, canvases and container controls). For listboxes, canvases and container controls check the Xojo Enabled property. If they are nested, you must check the parent.

Note that listboxes, canvases and container controls do not inherit from NSControl, but from NSView. This means they do not have an isEnabled property. This is the hierarchy:

ContainerControl –> XOJView –> NSView –> NSResponder –>NSObject
Canvas –> XOJView –> NSView –> NSResponder –>NSObject

RadioButton –> XOJButton –> NSButton –> NSControl –> NSView –> NSResponder –>NSObject

This is the code to get the hierarchy:

[code] Declare Function object_getClass Lib “libobjc.A.dylib” (id As Ptr) As Ptr
Declare Function class_getSuperclass Lib “libobjc.A.dylib” (id As Ptr) As Ptr
Declare Function class_getName Lib “libobjc.A.dylib” (id As Ptr) As CString

Dim hierarchy As String
Dim cls As Ptr

cls = object_getClass(Ptr(Me.Handle))
hierarchy = class_getName(cls)

Do
cls = class_getSuperclass(cls)
If cls = Nil Then
Exit
End
hierarchy = hierarchy + " –> " + class_getName(cls)
Loop[/code]