View Javadoc

1   /*
2    * Copyright 2002-2004 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    * 
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.springframework.richclient.command.support;
17  
18  import java.beans.PropertyChangeEvent;
19  import java.beans.PropertyChangeListener;
20  import java.lang.ref.WeakReference;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.NoSuchElementException;
24  import java.util.Set;
25  
26  import javax.swing.AbstractButton;
27  
28  import org.springframework.core.style.ToStringCreator;
29  import org.springframework.richclient.command.AbstractCommand;
30  import org.springframework.richclient.command.config.CommandButtonConfigurer;
31  import org.springframework.richclient.command.config.CommandFaceDescriptor;
32  import org.springframework.util.Assert;
33  import org.springframework.util.ObjectUtils;
34  
35  public class CommandFaceButtonManager implements PropertyChangeListener {
36      private Set buttons = new HashSet(6);
37  
38      private AbstractCommand command;
39  
40      private String faceDescriptorId;
41  
42      private CommandFaceDescriptor faceDescriptor;
43  
44      private static class ManagedButton {
45          private WeakReference buttonHolder;
46  
47          private CommandButtonConfigurer buttonConfigurer;
48          
49          private int hashCode;
50  
51          public ManagedButton(AbstractButton button, CommandButtonConfigurer buttonConfigurer) {
52              this.buttonHolder = new WeakReference(button);
53              this.buttonConfigurer = buttonConfigurer;
54              this.hashCode = button.hashCode();
55          }
56  
57          public AbstractButton getButton() {
58              return (AbstractButton)buttonHolder.get();
59          }
60  
61          public boolean equals(Object o) {
62          	if (o == null) {
63          		return false;
64          	}
65              if (this == o) {
66                  return true;
67              }
68              return ObjectUtils.nullSafeEquals(getButton(), ((ManagedButton)o).getButton());
69          }
70  
71          public int hashCode() {
72              return hashCode;
73          }
74      }
75  
76      public CommandFaceButtonManager(AbstractCommand command, String faceDescriptorKey) {
77          Assert.notNull(command, "The command to manage buttons for cannot be null");
78          Assert.hasText(faceDescriptorKey, "The face descriptor key is required");
79          this.command = command;
80          this.faceDescriptorId = faceDescriptorKey;
81      }
82  
83      public CommandFaceButtonManager(AbstractCommand command, CommandFaceDescriptor faceDescriptor) {
84          this.command = command;
85          setFaceDescriptor(faceDescriptor);
86      }
87  
88      public void setFaceDescriptor(CommandFaceDescriptor faceDescriptor) {
89          Assert.notNull(faceDescriptor, "The face descriptor for managing command button appearance is required");
90          if (!ObjectUtils.nullSafeEquals(this.faceDescriptor, faceDescriptor)) {
91              if (this.faceDescriptor != null) {
92                  this.faceDescriptor.removePropertyChangeListener(this);
93              }
94              this.faceDescriptor = faceDescriptor;
95              this.faceDescriptor.addPropertyChangeListener(this);
96              propertyChange(null);
97          }
98      }
99  
100     public CommandFaceDescriptor getFaceDescriptor() {
101         return faceDescriptor;
102     }
103 
104     public boolean isFaceConfigured() {
105         return this.faceDescriptor != null;
106     }
107 
108     public void attachAndConfigure(AbstractButton button, CommandButtonConfigurer strategy) {
109         Assert.notNull(button, "The button to attach and configure is required");
110         Assert.notNull(strategy, "The button configuration strategy is required");
111         if (!isAttachedTo(button)) {
112             ManagedButton managedButton = new ManagedButton(button, strategy);
113             if (buttons.add(managedButton)) {
114                 configure(button, strategy);
115             }
116         }
117     }
118 
119     private void cleanUp() {
120         for (Iterator i = buttons.iterator(); i.hasNext();) {
121             ManagedButton button = (ManagedButton)i.next();
122             if (button.getButton() == null) {
123                 i.remove();
124             }
125         }
126     }
127 
128     protected void configure(AbstractButton button, CommandButtonConfigurer strategy) {
129         if (this.faceDescriptor == null) {
130             if (command.getFaceDescriptorRegistry() != null) {
131                 setFaceDescriptor(command.getFaceDescriptorRegistry().getFaceDescriptor(command, faceDescriptorId));
132             } else {
133                 setFaceDescriptor(new CommandFaceDescriptor());
134             }
135         }
136 
137         getFaceDescriptor().configure(button, command, strategy);
138     }
139 
140     public void detach(AbstractButton button) {
141         buttons.remove(findManagedButton(button));
142     }
143 
144     public void detachAll() {
145         buttons.clear();
146     }
147 
148     public boolean isAttachedTo(AbstractButton button) {
149         return findManagedButton(button) != null;
150     }
151 
152     protected ManagedButton findManagedButton(AbstractButton button) {
153         Assert.notNull(button, "The button is required");
154         cleanUp();
155         for (Iterator i = buttons.iterator(); i.hasNext();) {
156             ManagedButton managedButton = (ManagedButton)i.next();
157             if (button.equals(managedButton.getButton())) {
158                 return managedButton;
159             }
160         }
161         return null;
162     }
163 
164     public Iterator iterator() {
165         cleanUp();
166         return new ButtonIterator(buttons.iterator());
167     }
168 
169     private static class ButtonIterator implements Iterator {
170         private Iterator it;
171 
172         private AbstractButton nextButton;
173 
174         public ButtonIterator(Iterator it) {
175             this.it = it;
176             fetchNextButton();
177         }
178 
179         public boolean hasNext() {
180             return nextButton != null;
181         }
182 
183         public Object next() {
184             if (nextButton == null) {
185                 throw new NoSuchElementException();
186             }
187             AbstractButton lastButton = nextButton;
188             fetchNextButton();
189             return lastButton;
190         }
191 
192         public void remove() {
193             throw new UnsupportedOperationException();
194         }
195 
196         private void fetchNextButton() {
197             while (it.hasNext()) {
198                 ManagedButton managedButton = (ManagedButton)it.next();
199                 nextButton = managedButton.getButton();
200                 if (nextButton != null) {
201                     return;
202                 }
203             }
204             nextButton = null;
205         }
206     }
207 
208     public void propertyChange(PropertyChangeEvent e) {
209         Iterator it = buttons.iterator();
210         while (it.hasNext()) {
211             ManagedButton mb = (ManagedButton)it.next();
212             Assert.notNull(mb, "Managed button reference cannot be null");
213             if (mb.getButton() == null) {
214                 it.remove();
215             }
216             else {
217                 configure(mb.getButton(), mb.buttonConfigurer);
218             }
219         }
220     }
221 
222     public String toString() {
223         return new ToStringCreator(this).append("commandId", command.getId())
224                 .append("faceDescriptor", faceDescriptor)
225                 .append("attachedButtonCount", buttons.size())
226                 .toString();
227     }
228 }