001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.core;
017    
018    import java.beans.PropertyChangeEvent;
019    import java.beans.PropertyChangeListener;
020    import java.util.Arrays;
021    import java.util.HashSet;
022    import java.util.Set;
023    
024    import javax.swing.JComponent;
025    import javax.swing.text.JTextComponent;
026    
027    import org.springframework.binding.value.ValueModel;
028    import org.springframework.rules.closure.support.Algorithms;
029    import org.springframework.rules.closure.support.Block;
030    
031    /**
032     * @author Keith Donald
033     */
034    public class GuardedGroup implements Guarded {
035        private Boolean groupEnabledState;
036    
037        private Set guardedGroup;
038    
039        private GuardedGroup() {
040    
041        }
042    
043        public GuardedGroup(Guarded[] guarded) {
044            this.guardedGroup = new HashSet(Arrays.asList(guarded));
045        }
046    
047        public void addGuarded(Guarded guarded) {
048            this.guardedGroup.add(guarded);
049        }
050    
051        public void addGuardedHolder(ValueModel guardedHolder) {
052            this.guardedGroup.add(new GuardedValueModel(this, guardedHolder));
053        }
054    
055        public boolean isEnabled() {
056            if (groupEnabledState == null) {
057                return false;
058            }
059            return groupEnabledState.booleanValue();
060        }
061    
062        public void setEnabled(final boolean enabled) {
063            if (this.groupEnabledState != null && this.groupEnabledState.booleanValue() == enabled) {
064                return;
065            }
066            Algorithms.instance().forEach(guardedGroup, new Block() {
067                protected void handle(Object guarded) {
068                    ((Guarded)guarded).setEnabled(enabled);
069                }
070            });
071            this.groupEnabledState = Boolean.valueOf(enabled);
072        }
073    
074        private static class GuardedValueModel implements Guarded, PropertyChangeListener {
075            private GuardedGroup guardedGroup;
076    
077            private ValueModel guardedHolder;
078    
079            public GuardedValueModel(GuardedGroup guardedGroup, ValueModel valueModel) {
080                this.guardedGroup = guardedGroup;
081                this.guardedHolder = valueModel;
082                this.guardedHolder.addValueChangeListener(this);
083            }
084    
085            public boolean isEnabled() {
086                Guarded g = (Guarded)guardedHolder.getValue();
087                if (g != null)
088                    return g.isEnabled();
089    
090                return false;
091            }
092    
093            public void setEnabled(boolean enabled) {
094                Guarded g = (Guarded)guardedHolder.getValue();
095                if (g != null) {
096                    g.setEnabled(enabled);
097                }
098            }
099            
100            public void propertyChange(PropertyChangeEvent evt) {
101                Boolean groupEnabled = GuardedValueModel.this.guardedGroup.groupEnabledState;
102                if (groupEnabled != null) {
103                    setEnabled(groupEnabled.booleanValue());
104                }
105            }
106        }
107    
108        public static final Guarded createGuardedAdapter(final JComponent component) {
109            if (component instanceof JTextComponent) {
110                // JTextComponents are different from most JComponents in that
111                // they are best disabled by invoking the setEditable method.
112                // setEnabled(false) completely disables the control -- including
113                // the ability to copy to the clipboard.
114                final JTextComponent textComp = (JTextComponent)component;
115                return new Guarded() {
116                    public boolean isEnabled() {
117                        return textComp.isEditable();
118                    }
119    
120                    public void setEnabled(boolean enabled) {
121                        textComp.setEditable(enabled);
122                    }
123                };
124            }
125    
126            return new Guarded() {
127                public boolean isEnabled() {
128                    return component.isEnabled();
129                }
130    
131                public void setEnabled(boolean enabled) {
132                    component.setEnabled(enabled);
133                }
134            };
135        }
136    
137        private static final Guarded createGuardedAdapter(final Object component) {
138            if (component.getClass().isArray())
139                return doCreateGuardedGroup((Object[])component);
140    
141            return createGuardedAdapter((JComponent)component);
142        }
143    
144        public static final GuardedGroup createGuardedGroup(Object[] components) {
145            return doCreateGuardedGroup(components);
146        }
147    
148        public static final GuardedGroup createGuardedGroup(final JComponent[] components) {
149            return doCreateGuardedGroup(components);
150        }
151    
152        public static final GuardedGroup createGuardedGroup(JComponent[][] componentArrays) {
153            return doCreateGuardedGroup(componentArrays);
154        }
155    
156        private static GuardedGroup doCreateGuardedGroup(Object[] components) {
157            Set guardedSet = new HashSet(components.length);
158            for (int i = 0; i < components.length; i++) {
159                guardedSet.add(createGuardedAdapter(components[i]));
160            }
161            GuardedGroup g = new GuardedGroup();
162            g.guardedGroup = guardedSet;
163            return g;
164        }
165    
166    }