|
Replies:
18
-
Last Post:
Apr 9, 2006 7:46 PM
by: twalljava
|
|
|
|
|
|
|
Enabling/Disabling Containers
Posted:
Mar 9, 2006 3:44 PM
|
|
|
Hey folks,
In the wacky wiki is this little item:
http://wiki.java.net/bin/view/Javadesktop/SwingLabsWackyWiki#JXFrame_JXDialog_JXPanel_JXTabbe
This is related to a P1 issue in the issue tracker:
https://swingx.dev.java.net/issues/show_bug.cgi?id=88
Amy did some research several years ago as to how to implement this in Swing (since, like me, it was really bothering to her that JPanel, JFrame, etc didn't honor setEnabled). It turns out to be a tricky problem.
Solution Attempt #1: Recursion and Client Properties
This takes a direct approach to the problem. Recurse down the containment heirarchy whenever setEnabled() is flipped to false in a container (JXFrame, for instance). For each child component, put a client property into the component indicating its old enabled state. Flip the state of the component to match its parent. Recurse.
On restoring state, of course take it out of the client property map and restore the component.
The approach is simple, straitforward, and unfortunately doesn't answer some nagging edge cases. For example:
JCheckBox cbox = new JCheckBox("Watch me");
JXRadioGroup grp = new JXRadioGroup();
grp.add("Some Value");
grp.add("Some other value");
grp.add(cbox);
grp.setEnabled(false);
cbox.setEnabled(true);
(You can imagine something similar when using JXPanel, etc)
What should cbox.isEnabled() return? Should the cbox.setEnabled() call override the grp.setEnabled call?
If you answer "yes", then perhaps this approach works. If you say "no", then obviously this approach is flawed.
Solution Attempt #2: Override isEnabled
This solution is only fit for implementing in Swing/AWT, because it means changing AWT. Component could contain code like this:
public boolean isInheritDisabled() {
return inheritDisabled;
}
public void setInheritDisabled(boolean b){...}
public boolean isEnabled() {
if (isInheritDisabled()) {
boolean parentDisabled =
getParent() == null ?
false : !getParent().isEnabled();
if (parentDisabled) {
return true;
}
}
return enabled;
}
(I may have goofed the logic in this code, it hasn't been tested, it is just a demonstration of the idea).
There's also logic for setEnabled a new protected method that would need to be created to ensure that property change listeners are called appropriately, etc.
Of the two approaches, the first looks appropriate for SwingLabs, and the second looks correct for Swing/AWT.
I mention all this, along with the general question: "Do you think JXFrame, JXPanel, JXDialog, JXTabbedPane and JXRadioGroup should be part of the calculation for whether a component should be enabled?"
Thoughts? Coding up the first approach is a short matter if we once agree to do it.
Richard
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 9, 2006 4:09 PM
in response to: rbair
|
|
|
+1 on the 1st approach. If I disable the frame, then I would expect the entire world to be disabled.
Erik
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 9, 2006 7:43 PM
in response to: rbair
|
|
|
> This takes a direct approach to the problem. Recurse down the containment heirarchy whenever setEnabled() is flipped to false in a container (JXFrame, for instance). > For each child component, put a client property into the component indicating its old enabled state. Flip the state of the component to match its parent. Recurse.
> On restoring state, of course take it out of the client property map and restore the component.
> The approach is simple, straitforward, and unfortunately doesn't answer some nagging edge cases. > For example:
JCheckBox cbox = new JCheckBox("Watch me");
JXRadioGroup grp = new JXRadioGroup();
grp.add("Some Value");
grp.add("Some other value");
grp.add(cbox);
grp.setEnabled(false);
cbox.setEnabled(true);
> What should cbox.isEnabled() return? Should the cbox.setEnabled() call override the grp.setEnabled call?
> If you answer "yes", then perhaps this approach works. > If you say "no", then obviously this approach is flawed.
I say the answer is no. I agree that if the container is disabled, all components should be disabled.
I think you are trying to get away with minimal changes. Changes should not be a problem in Swingx.
I suggest three fields, e. g.:
boolean enabled; /* same as at present */
boolean containerEnabled; /* reflects container status */
boolean oldEnabled; /* original value of enabled */
Possibly containerEnabled could be replaced by a protected isContainerEnabled() method in the container.
If the container is set enabled(false): enabled is stored in oldEnabled enabled set false containerEnabled set false
If the container is set enabled(true): oldEnabled moved back to enabled containerEnabled set true
In the above example, if containerEnabled is false, the cbox.setEnabled(true) would not effect enabled. It is open for discussion whether it should effect oldEnabled.
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 9, 2006 7:58 PM
in response to: rturnbull
|
|
|
Hey Ray,
Thanks for your input.
>I think you are trying to get away with minimal changes. >Changes should not be a problem in Swingx.
Yes, I'm definitely trying to limit the number of changes. But, I also have to make sure that what we do in SwingX mixes well with other components. Because of that, I'm not sure there is anything else I can do besides option #1: disable everything recursively.
>I suggest three fields, e. g.: >>boolean enabled; /* same as at present */
>boolean containerEnabled; /* reflects container status */
>boolean oldEnabled; /* original value of enabled */
>
> >Possibly containerEnabled could be replaced by a protected >isContainerEnabled() method in the container. > >If the container is set enabled(false): > enabled is stored in oldEnabled > enabled set false > containerEnabled set false > >If the container is set enabled(true): > oldEnabled moved back to enabled > containerEnabled set true > >In the above example, if containerEnabled is false, the >cbox.setEnabled(true) would not effect enabled. >It is open for discussion whether it should effect oldEnabled.
Is this a proposal for SwingX or Swing?
Cheers Richard
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 4:07 AM
in response to: rbair
|
|
|
Hi Folks,
happy dreaming 
My hypothesis:
The problem is near-to unsolvable in the general case. That's why it is not part of core Swing.
Technically, the disable-and-store-old-state followed by a enable-and-restore-to-old-state might look attractive. It even might be a nice-to-have in special cases. But there are (at least, probably a bunch more) two issues with that.
*Compound components*
The recursion must stop on a "compound component" (or "single entity" as Noel calls it in #88-swingx). Then the component is responsible for keeping dependent's state. There's no general way to detect such a component - examples are JComboBox, JXDatePicker (which as related issue https://swingx.dev.java.net/issues/show_bug.cgi?id=275)
To make things even more complicated, dependents don't need to be under the hierarchy of the "compound component", f.i. JXTable takes care of the ColumnControl's (and header's) enabled state.
Trying to tackle both would require to have
a) a property on the compound: "don't touch my children" and b) a property on the uncontained dependents: "don't touch me"
*Binding to enabled*
enable-and-update-to-old might break application state if the enabled status is bound to a (presentation or other) model property and that property changed in-the-meantime - now the old-state is invalid.
Trying to tackle that would require to have
c) a "real" stored-old-enabled-due-to-view-concerns property d) bind the presentation model property to both the enabled and the stored-old-enabled
JXRadioGroup has a variant of that problem: On disabling - the group itself or the general controller - keeps track of the old-enabled of every button. Button's enabled is controlled by the Action - if there is an Action. So the enabled controller needs to restore to old-enabled or to action's enabled. During group's disabled (as-group) a problem looms if the Action's enabled was false on storing and changed to true. Another if actions are added.
Now imagine the complexity of state transitions when overloading a)-- d) <g>
Successful permuting!
Jeanette
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 9:41 AM
in response to: Kleopatra
|
|
|
Hey Jeanette
> happy dreaming 
:-D
> The problem is near-to unsolvable in the general > case. That's why it is > not part of core Swing.
Difficult, but I think it is certainly solveable. The points you've listed are all absolutely valid with the recursive approach, but I don't think they are a problem at all with the second approach I listed (which we can't do for SwingX but could do for Swing). So each point you have below I'll address twice, once for the recursion technique and once for the "fix AWT" technique (quick refresher: this requires changing AWT/Swing so that each component queries its own state and its parents state to determine whether it is really enabled, rather than the parent forcefully changing anything on the child components or recursing).
> *Compound components* > > The recursion must stop on a "compound component" (or > "single entity" as > Noel calls it in #88-swingx). Then the component is > responsible for > keeping dependent's state. There's no general way to > detect such a > component - examples are JComboBox, JXDatePicker > (which as related issue > https://swingx.dev.java.net/issues/show_bug.cgi?id=275 > )
Yep!
Recursion: Obviously this applies to recursion. For our purposes we can install a client property on our compound components.
Fix AWT/Swing: Even though this wouldn't be necessary for this technique to work (since it is about children pointing towards parents rather than the other way around), it is still something that should be thought about for Swing. It seems like a generally useful property to have on a Swing component because this isn't the first time recursion has been used on a component tree!
> To make things even more complicated, dependents > don't need to be under > the hierarchy of the "compound component", f.i. > JXTable takes care of > the ColumnControl's (and header's) enabled state.
I haven't thought about this edge case! It does seem like this simply won't be handled properly with technique recursion, but with the "real" fix in AWT/Swing this wouldn't be a problem (the header would be overridden to not pay attention to the parent, and the table would ensure that the header is handled properly).
> *Binding to enabled* > > enable-and-update-to-old might break application > state if the enabled > status is bound to a (presentation or other) model > property and that > property changed in-the-meantime - now the old-state > is invalid.
First, I don't think this is a sufficiently large issue to even worry about. Currently the enabled state of a container (JFrame/JPanel/any of the others, I believe) doesn't even do anything, though I need to verify that. I'm dubious that anybody has ever tied the enabled state of a JPanel to any application data of any kind simply because the panel doesn't do anything when disabled.
Second, I think that if I have some application state tied to whether a checkbox is enabled, then if the parent becomes disabled I would want the checkbox to be disabled AND to notify me through the normal channels that it is disabled.
In other words, the behavior is what I would expect. Why is this a problem? Convince me 
> JXRadioGroup has a variant of that problem: On > disabling - the group > itself or the general controller - keeps track of the > old-enabled of > every button. Button's enabled is controlled by the > Action - if there is > an Action. So the enabled controller needs to restore > to old-enabled or > to action's enabled. During group's disabled > (as-group) a problem looms > if the Action's enabled was false on storing and > changed to true. > Another if actions are added.
For the recursive technique, this is mearly another manifestation of the previously mentioned problem, namely:
JPanel panel = ...
JCheckBox cbox = ...
panel.add(cbox);
panel.setEnabled(false);
cbox.setEnabled(true);
yields cbox.isEnabled() == true when it should be false (at least, that's what we all seem to agree with).
Fix Swing/AWT: This wouldn't be a problem because you could toggle "enabled" all day long and it won't be until the parent is also effectively enabled that the child will notify its "true" state.
The only real gotcha that I've found so far with the Fix Swing/AWT approach is that anybody who's overridden isEnabled will have to make a call to super or may not perform as expected. But I don't think this is a backwards incompatible change because, as I mentioned before, JFrame/JPanel don't do anything with the enabled bit today.
Thanks for the feedback! Keep it coming 
Richard
PS> WHOA. I just learned that calling setEnabled(false) on a JFrame is a really bad thing to do. It disables the window, making it impossible to re-enable it. Or at least, I can't re-enable it. Likewise, I'm not succeeding in closing them either from their "X" button or from the tray! Oh great.
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 7:02 AM
in response to: rbair
|
|
|
Hi Richard,
> >>The problem is near-to unsolvable in the general >>case. That's why it is >>not part of core Swing. > > > Difficult, but I think it is certainly solveable.
okay - so I'll revise my statement: unsolvable without api changes in AWT/Swing bowels. Hope to be proved wrong, though With Mustang nearly ready, any chance to get it into it? Or are we talking about Dolphin?
In the other mail, I started a summary of requirements - I would like to get a clearer idea about the "what" before going into details as to the "how" (didn't stick to that myself in my first examples, been playing devil's advocate .
Cheers Jeanette
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 4:00 PM
in response to: Kleopatra
|
|
|
> >>The problem is near-to unsolvable in the general > >>case. That's why it is > >>not part of core Swing. > > > > > > Difficult, but I think it is certainly solveable. > > > okay - so I'll revise my statement: unsolvable > without api changes in > AWT/Swing bowels. Hope to be proved wrong, though 
I'm afraid you are right about that. I can't see any way of doing it outside of core swing.
Here's part of a test case that shows the deep underlying problem:
assertTrue(textField.isEnabled());
//disable the pane and disable the component
pane.setEnabled(false);
textField.setEnabled(false);
assertFalse(textField.isEnabled());
//enable the pane and assert that the text field is now disabled
pane.setEnabled(true);
assertFalse(textField.isEnabled());
This fails on the last assert. The problem is that when the pane is disabled, the text field is also implicitly disabled so that textField.isEnabled() will return false. Of course, I keep its "original" state so I can restore it later. However, in the meantime the developer calls textField.setEnabled(false), indicating that the text field should be disabled when the container is re-enabled. Alas, it doesn't happen because the property change event is never fired because the property hasn't changed.
So we can't do the full 100% solution outside of the JDK. That means:
* Do we compromise and go half way? * Do we chalk it up to experience and wait for Dolphin?
> With Mustang > nearly ready, any chance to get it into it? Or are we > talking about > Dolphin?
Dolphin
Later Richard
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 7:26 PM
in response to: rbair
|
|
|
What about something like this:
public void installFixerOnComponent(Component component) {
component.addPropertyListener("enabled", new PropertyListener() {
public void propertyChanged(PropertyChangeEvent e) {
fixComponentInEnabledContainerLater(component);
}
}
}
public void fixComponentInEnabledContainerLater(final Component component) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
boolean componentIsEnabled = component.isEnabled();
boolean containerIsEnabled = container.isEnabled();
if(!containerIsEnabled && componentIsEnabled) {
component.setEnabled();
}
}
});
}
This is a hack, but it will get the job done. Since it's on an invokeLater(), you probably won't have any repaints done while the component's in the disabled state.
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 7:33 PM
in response to: jessewilson
|
|
|
Hey Jesse,
I don't think it will work. The problem is that the property change event never gets fired.
1# pane.setEnabled(false); 2# textField.setEnabled(false);
Right here on line #2 is where it doesn't work. pane.setEnabled(false) disables the parent, and also the children (saving the children's original state, in this case, true for textField).
On line #2 I try to change the "original" state of the textField so that when the pane is re-enabled the textField will remain disabled. However, line #2 never notifies anybody. The call fails silently. That's my problem.
Richard
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 11:29 AM
in response to: Kleopatra
|
|
|
Note that I attempted to solve this for Swing about 6 years ago and came [with great despair] to the same conclusion as Jeanette. We should have tackled this early in the AWT days to really get it right.
But it doesn't hurt to try to provide some convenience routines to make it easier, so I encourage your exploration on the problem!
Aim
On Mar 10, 2006, at 4:07 AM, Kleopatra wrote:
> Hi Folks, > > happy dreaming  > > My hypothesis: > > The problem is near-to unsolvable in the general case. That's why > it is not part of core Swing. > > Technically, the disable-and-store-old-state followed by a enable- > and-restore-to-old-state might look attractive. It even might be a > nice-to-have in special cases. But there are (at least, probably a > bunch more) two issues with that. > > > *Compound components* > > The recursion must stop on a "compound component" (or "single > entity" as Noel calls it in #88-swingx). Then the component is > responsible for keeping dependent's state. There's no general way > to detect such a component - examples are JComboBox, JXDatePicker > (which as related issue > https://swingx.dev.java.net/issues/show_bug.cgi?id=275) > > To make things even more complicated, dependents don't need to be > under the hierarchy of the "compound component", f.i. JXTable takes > care of the ColumnControl's (and header's) enabled state. > > Trying to tackle both would require to have > > a) a property on the compound: "don't touch my children" and > b) a property on the uncontained dependents: "don't touch me" > > > *Binding to enabled* > > enable-and-update-to-old might break application state if the > enabled status is bound to a (presentation or other) model property > and that property changed in-the-meantime - now the old-state is > invalid. > > > Trying to tackle that would require to have > > c) a "real" stored-old-enabled-due-to-view-concerns property > d) bind the presentation model property to both the enabled and the > stored-old-enabled > > JXRadioGroup has a variant of that problem: On disabling - the > group itself or the general controller - keeps track of the old- > enabled of every button. Button's enabled is controlled by the > Action - if there is an Action. So the enabled controller needs to > restore to old-enabled or to action's enabled. During group's > disabled (as-group) a problem looms if the Action's enabled was > false on storing and changed to true. Another if actions are added. > > > Now imagine the complexity of state transitions when overloading > a)-- d) <g> > > Successful permuting! > > Jeanette > > --------------------------------------------------------------------- > To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net > For additional commands, e-mail: jdnc-help@jdnc.dev.java.net >
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 3:32 PM
in response to: Amy Fowler
|
|
|
heh, Ive put a patch in for essentially the same issue. My personal take is:
setEnabled should not determine at this juncture what the children do, unless of course the parent overrides the method to alter the children's set. As I say in my patch, this method has been this way forever, there may be clients that actually depend upon it.
Though to help the clients out, Ive created a simple method called recursiveEnable that walks the component tree and synchs the behavior of the tree to the topmost calling widget.
that's my two cents,  leouser
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 4:26 PM
in response to: leouser
|
|
|
> Though to help the clients out, Ive created a simple > method called recursiveEnable that walks the > component tree and synchs the behavior of the tree to > the topmost calling widget.
This is a third approach, though I wouldn't add it to JFrame/JPanel/etc if I were you. I'd let it be a simple utility method in SwingUtilities.
The problem is that when somebody calls recursiveEnable(false), they are expecting that they are setting state. That it is trivial to circumvent this state (as shown in previous messages, just set any child component to a different state) invalidates that mental model.
By moving the logic into a utility class you can get around that preconception (maybe) by convincing people that its a one time method call, rather than some state on the component (and implicitly on subcomponents).
My problem really is that I want to have some state on a container that manages what the child components enabled property really is. I'm not interested in setEnabled() as much as in isEnabled(). You can call setEnabled(true), in my world, and have isEnabled() return false if the parent is also disabled.
I like that model a lot more.
> that's my two cents, 
Thanks! Richard
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 10, 2006 4:44 PM
in response to: rbair
|
|
|
Its fairly clear in the javadoc what the function does, so the user shouldn't be confused about what is going to happen. After that it doesn't concern itself with what happens with the child components and it probably shouldn't. I actually like the idea that the user is free to determine child states after its done. Its target component is the Container class, at this juncture.
leouser
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 5:57 AM
in response to: Amy Fowler
|
|
|
Amy Fowler wrote:
> > But it doesn't hurt to try to provide some convenience routines to > make it easier, > so I encourage your exploration on the problem! >
Exploration is always fun, but takes resources We are very thin-spread, the project has lost two developers (not even counting you as project lead) since Nov 2004 and Richard occasionally seems to have a bunch of responsibilities not directly related to SwingLabs ...
That said, let's have some fun: one step back and define the task in terms of problem space instead of in terms of speculative solution space. Thinking aloud ...
What we want is a kind of "DisableController" (note this is just the concept, not necessarily a class nor does is imply a top-down approach) - it should control the enabled property of all components in the hierarchy of a given container: what we are really after is a guaranteed "disabled" of all children under certain conditions. There's a life cycle aspect involved - we could model it as a on/off property of the controller, its responsibilities are limited to the "on" time, does nothing if it is "off".
The controller is responsible for
a) on transition off --> on: guarantees that all children are in disabled state after the transitions is completed b) during the on period: guarantees to keep all children in disabled state c) on transition on --> off: does its best to set each child's enabled property to whatever is appropriate at that moment.
The really tricky parts are b) and c) because "outside" clients/events might have tried to change the child's enabled during the controller's on-period. The controller must honor the intended change, IMO. Examples for such changes
- adding a component to the hierarchy - explicit setting by view-realm program code - implicit setting by being bound to the enabled property of another component - implicit setting by a bound application property - ??
To me it looks like a three-property problem similar to what Ray suggested:
controller on/off == containerEnabled enabled == enabled restorable-enabled == oldEnabled
To play with solutions, we probably should have a zoo of small examples to run against - doing our dirtiest to make them fail <g> Hmm, maybe we should have a dedicated src tree in the incubator for everybody interested to contribute?
Jeanette
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Apr 7, 2006 1:43 AM
in response to: Kleopatra
|
|
|
[att1.html] package org.jdesktop.swingx.util;
import java.awt.Component; import java.awt.Container; import java.util.HashMap; import java.util.Map;
/** * Some utility methods for dealing with enabled/disabled state. * * @author Noel Grandin noelgrandin@gmail.com */ public class ComponentEnableUtils {
/** * Recursively enable/disable all components in the hierarchy under parent */ public void setEnabledRecursively(Container component, boolean enabled) { component.setEnabled(enabled); final int cnt = component.getComponentCount(); for (int i=0; i<cnt; i++) { Component child = component.getComponent(i); if (child instanceof Container) { setEnabledRecursively((Container) child, enabled); } else { child.setEnabled(enabled); } } }
/* getEnabledStateRecursively(Container component) { Map<Component, Boolean> map = new HashMap<Component, Boolean>(); map.put(component, component.isEnabled()); getEnabledStateRecursivelyInternal(map, component); return map; }
private void getEnabledStateRecursivelyInternal(Map<Component, Boolean> map, Container component) { final int cnt = component.getComponentCount(); for (int i=0; i<cnt; i++) { final Component child = component.getComponent(i); map.put(child, child.isEnabled()); if (child instanceof Container) { getEnabledStateRecursivelyInternal(map, (Container) child); } } } public enum ApplyEnabledState { IGNORE, ENABLE, DISABLE; } /* enabledState, ApplyEnabledState newComponentState) { applyState(component, enabledState, newComponentState); applyInternal(component, enabledState, newComponentState); }
private void applyInternal(Container component, Map<Component, Boolean> enabledState, ApplyEnabledState newComponentState) { final int cnt = component.getComponentCount(); for (int i=0; i<cnt; i++) { final Component child = component.getComponent(i); applyState(child, enabledState, newComponentState); if (child instanceof Container) { applyInternal((Container) child, enabledState, newComponentState); } } } private void applyState(Component component, Map<Component, Boolean> enabledState, ApplyEnabledState newComponentState) { final Boolean bool = enabledState.get(component); if (bool!=null) { component.setEnabled(bool.booleanValue()); } else { if (newComponentState==ApplyEnabledState.DISABLE) { component.setEnabled(false); } else if (newComponentState==ApplyEnabledState.ENABLE) { component.setEnabled(true); } } } }
NOTICE: Please note that this email, and the contents thereof, are subject to the standard Peralex email disclaimer, which may be found at: http://www.peralex.com/disclaimer.html
If you cannot access the disclaimer through the URL attached and you wish to receive a copy thereof please send an email to email@peralex.com
--------------------------------------------------------------------- To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Apr 9, 2006 7:46 PM
in response to: Noel Grandin
|
|
|
Usually, when you disable a container and desire for all of its contents to be disabled, you have the intent of restoring that state at some future point. I don't think it makes sense to scatter state throughout the hierarchy for an action that is well-localized. Why not keep the state local to the action doing the disable? For example:
/** Returns a list of all previously enabled things which were disabled. */ List disable(Container root) { // generate the enabled list first, then disable // the components. List enabled = findEnabled(root, new ArrayList()); for (Iterator i=enabled.iterator();i.hasNext();) { ((Component)i.next()).setEnabled(false); } }
List findEnabled(Container root, List soFar) { // recurse root appropriately, adding all components // found which are currently enabled // ... if (root.isEnabled()) soFar.add(root); return soFar; }
void restore(List disabled) { for (Iterator i=disable.iterator();i.hasNext();) { ((Component)i.next()).setEnabled(true); } }
This might have issues on "restore" if there are side effects to calling setEnabled which work both up AND down the hierarchy.
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 12, 2006 5:40 PM
in response to: Kleopatra
|
|
|
I still like my method with the three fields.
I suggested it for swingx, but I don't see why it wouldn't work in swing.
The only proviso in swingx is that you would have to be all swingx, no mix and match with swing, so it might require a few more swingx components to fill the gaps.
As for the suggested problems:
> *Compound components A container would only enable/disable its children to one level. As Richard suggested, each compound component (or child) will decide for itself what to do when it is disabled. It may repeat over its children, or do nothing. So f.i JXTable will do the same as it does now. If I create a component consisting of a number of other components, I will need to write a setEnabled() method for the compound component, and include the controlling fields.
>*Binding to enabled* If the component is disabled by its container, attempts to enable it will only change the old-enabled state. Then when the container is enabled, the component should be restored to its correct state. I don't think there would be a need to bind the presentation model to both the enabled and old-enabled properties. If the container is disabled, its components should never show as enabled. I'm not sure of the exact mechanism use to bind e.g. a button to its action - that may need to be reworked a little.
It's possible (probable ) I've overlooked something, but it looks OK to me
|
|
|
|
|
|
|
|
Re: Enabling/Disabling Containers
Posted:
Mar 13, 2006 11:06 AM
in response to: rturnbull
|
|
|
> I still like my method with the three fields. > > I suggested it for swingx, but I don't see why it > wouldn't work in swing. > > The only proviso in swingx is that you would have to > be all swingx, no mix and match with swing, so it > might require a few more swingx components to fill > the gaps.
That's the part that bothers me. I think we have to make it work for SwingX + Swing + Well Behaved Third Party. Otherwise I'm afraid we'll introduce more confusion and false bugs. If/When implemented in Swing this will be taken care of naturally, but for SwingX we have to be... um... clever, and sometimes a bit hacky .
Later Richard
|
|
|
|
|