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.command.support; 017 018 import java.beans.PropertyChangeEvent; 019 import java.beans.PropertyChangeListener; 020 import java.lang.ref.WeakReference; 021 import java.util.HashSet; 022 import java.util.Iterator; 023 import java.util.NoSuchElementException; 024 import java.util.Set; 025 026 import javax.swing.AbstractButton; 027 028 import org.springframework.core.style.ToStringCreator; 029 import org.springframework.richclient.command.AbstractCommand; 030 import org.springframework.richclient.command.config.CommandButtonConfigurer; 031 import org.springframework.richclient.command.config.CommandFaceDescriptor; 032 import org.springframework.util.Assert; 033 import org.springframework.util.ObjectUtils; 034 035 public class CommandFaceButtonManager implements PropertyChangeListener { 036 private Set buttons = new HashSet(6); 037 038 private AbstractCommand command; 039 040 private String faceDescriptorId; 041 042 private CommandFaceDescriptor faceDescriptor; 043 044 private static class ManagedButton { 045 private WeakReference buttonHolder; 046 047 private CommandButtonConfigurer buttonConfigurer; 048 049 private int hashCode; 050 051 public ManagedButton(AbstractButton button, CommandButtonConfigurer buttonConfigurer) { 052 this.buttonHolder = new WeakReference(button); 053 this.buttonConfigurer = buttonConfigurer; 054 this.hashCode = button.hashCode(); 055 } 056 057 public AbstractButton getButton() { 058 return (AbstractButton)buttonHolder.get(); 059 } 060 061 public boolean equals(Object o) { 062 if (o == null) { 063 return false; 064 } 065 if (this == o) { 066 return true; 067 } 068 return ObjectUtils.nullSafeEquals(getButton(), ((ManagedButton)o).getButton()); 069 } 070 071 public int hashCode() { 072 return hashCode; 073 } 074 } 075 076 public CommandFaceButtonManager(AbstractCommand command, String faceDescriptorKey) { 077 Assert.notNull(command, "The command to manage buttons for cannot be null"); 078 Assert.hasText(faceDescriptorKey, "The face descriptor key is required"); 079 this.command = command; 080 this.faceDescriptorId = faceDescriptorKey; 081 } 082 083 public CommandFaceButtonManager(AbstractCommand command, CommandFaceDescriptor faceDescriptor) { 084 this.command = command; 085 setFaceDescriptor(faceDescriptor); 086 } 087 088 public void setFaceDescriptor(CommandFaceDescriptor faceDescriptor) { 089 Assert.notNull(faceDescriptor, "The face descriptor for managing command button appearance is required"); 090 if (!ObjectUtils.nullSafeEquals(this.faceDescriptor, faceDescriptor)) { 091 if (this.faceDescriptor != null) { 092 this.faceDescriptor.removePropertyChangeListener(this); 093 } 094 this.faceDescriptor = faceDescriptor; 095 this.faceDescriptor.addPropertyChangeListener(this); 096 propertyChange(null); 097 } 098 } 099 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 }