That a good question wrt Windows. In a Swing app, I believe this would disable all the content, not the window, as they are under control of the OS in general.
The recursive search should work fine with nested controls, but only once they are parented. This implies that if you have to run some code to do the actual disabling (probably changing visuals somehow), then that code would have to get run when the control is added to it’s parents (do you already have hooks for this?). Maybe some nicer code than mine would illustrate it better (it’s actually where I stole the pattern above from more or less). I use the Wicket web framework quite a lot, and this has setEnabled() in its top level “Component”.
Here are the relevant methods (i have stripped out some Wicket specific stuff) …
[java]
/**
* @return true if this component is authorized to be enabled, false otherwise
*/
public final boolean isEnableAllowed()
{
return isActionAuthorized(ENABLE);
}
/**
* Gets whether this component is enabled. Specific components may decide to implement special
* behavior that uses this property, like web form components that add a disabled='disabled'
* attribute when enabled is false.
*
* @return Whether this component is enabled.
*/
public boolean isEnabled()
{
return getFlag(FLAG_ENABLED);
}
/**
* Sets whether this component is enabled. Specific components may decide to implement special
* behavior that uses this property, like web form components that add a disabled='disabled'
* attribute when enabled is false. If it is not enabled, it will not be allowed to call any
* listener method on it (e.g. Link.onClick) and the model object will be protected (for the
* common use cases, not for programmer's misuse)
*
* @param enabled
* whether this component is enabled
* @return This
*/
public final Component setEnabled(final boolean enabled)
{
// Is new enabled state a change?
if (enabled != getFlag(FLAG_ENABLED))
{
// Tell the page that this component's enabled was changed
if (isVersioned())
{
final Page page = findPage();
if (page != null)
{
addStateChange();
}
}
// Change visibility
setFlag(FLAG_ENABLED, enabled);
onEnabledStateChanged();
}
return this;
}
void clearEnabledInHierarchyCache()
{
setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET, false);
}
void onEnabledStateChanged()
{
clearEnabledInHierarchyCache();
}
/**
* Calculates enabled state of the component taking its hierarchy into account. A component is
* enabled iff it is itself enabled ({@link #isEnabled()} and {@link #isEnableAllowed()} both
* return true
), and all of its parents are enabled.
*
* @return true
if this component is enabled
*/
public final boolean isEnabledInHierarchy()
{
if (getRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET))
{
return getRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_VALUE);
}
final boolean state;
Component parent = getParent();
if (parent != null && !parent.isEnabledInHierarchy())
{
state = false;
}
else
{
state = isEnabled() && isEnableAllowed();
}
setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET, true);
setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_VALUE, state);
return state;
}
[/java]
This actually does some other funky stuff like caching the calculated enabled state. Wicket is slightly different in the the enabled state will mostly likely get pulled at the time of rendering, rather than earlier as would be likely with Tonegod.
It also has the concept of ‘isEnabledAllowed’. This is because in Wicket you often override the “isEnabled” method to calculate the state. The isEnableAllowed allows external code to override these overrides. I don’t think anything like that will be needed here.
I think you are right though, actual behavior should be taken case by case. In general, all input should always be blocked as soon as a control or any of it’s parents are disabled. With Swing, not all components actually visually change themselves when disabled. For example, disabling a Table stops you doing anything with it, but it still looks the same. I can’t think of a good reason for this though, nearly everything else “greys” itself out.