1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 }