1 24 package org.riotfamily.forms.element.collection; 25 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.Collections ; 29 import java.util.Comparator ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.Set ; 33 34 import org.riotfamily.common.beans.PropertyUtils; 35 import org.riotfamily.forms.Container; 36 import org.riotfamily.forms.DHTMLElement; 37 import org.riotfamily.forms.Editor; 38 import org.riotfamily.forms.ElementFactory; 39 import org.riotfamily.forms.ErrorUtils; 40 import org.riotfamily.forms.TemplateUtils; 41 import org.riotfamily.forms.element.TemplateElement; 42 import org.riotfamily.forms.event.Button; 43 import org.riotfamily.forms.event.ClickEvent; 44 import org.riotfamily.forms.event.ClickListener; 45 import org.riotfamily.forms.request.FormRequest; 46 import org.riotfamily.forms.resource.FormResource; 47 import org.riotfamily.forms.resource.ResourceElement; 48 import org.riotfamily.forms.resource.Resources; 49 import org.springframework.beans.BeanUtils; 50 import org.springframework.util.StringUtils; 51 52 53 56 public class ListEditor extends TemplateElement implements Editor, 57 ResourceElement, DHTMLElement { 58 59 60 private Class collectionClass; 61 62 private String parentProperty; 63 64 65 private ElementFactory itemElementFactory; 66 67 68 private Container items = new Container(); 69 70 71 private Button addButton; 72 73 private int minSize; 74 75 private int maxSize; 76 77 private boolean sortable; 78 79 public ListEditor() { 80 addComponent("items", items); 81 addButton = new Button(); 82 addButton.setLabelKey("label.form.list.add"); 83 addButton.setLabel("Add"); 84 addButton.addClickListener(new ClickListener() { 85 public void clicked(ClickEvent event) { 86 addItem(); 87 } 88 }); 89 addComponent("addButton", addButton); 90 setTemplate(TemplateUtils.getTemplatePath(ListEditor.class)); 91 } 92 93 public void setSortable(boolean sortable) { 94 this.sortable = sortable; 95 } 96 97 public boolean isSortable() { 98 return sortable; 99 } 100 101 public void setMinSize(int minSize) { 102 this.minSize = minSize; 103 } 104 105 public void setMaxSize(int maxSize) { 106 this.maxSize = maxSize; 107 } 108 109 public void setRequired(boolean required) { 110 minSize = required ? 1 : 0; 111 } 112 113 public boolean isRequired() { 114 return minSize != 0; 115 } 116 117 public void setParentProperty(String parentProperty) { 118 this.parentProperty = parentProperty; 119 } 120 121 public FormResource getResource() { 122 return sortable ? Resources.SCRIPTACULOUS_DRAG_DROP : null; 123 } 124 125 132 public void setCollectionClass(Class collectionClass) { 133 this.collectionClass = collectionClass; 134 } 135 136 139 public void setItemElementFactory(ElementFactory itemElementFactory) { 140 this.itemElementFactory = itemElementFactory; 141 } 142 143 146 public void setValue(Object value) { 147 if (collectionClass == null) { 148 Class type = getEditorBinding().getPropertyType(); 149 if (type.isInterface()) { 150 if (Set .class.isAssignableFrom(type)) { 151 collectionClass = HashSet .class; 152 } 153 else { 154 collectionClass = ArrayList .class; 155 } 156 } 157 else { 158 collectionClass = type; 159 } 160 } 161 if (value != null) { 162 if (!(value instanceof Collection )) { 163 throw new IllegalArgumentException ("Value must implement " + 164 "the java.util.Collection interface"); 165 } 166 Collection collection = (Collection ) value; 167 Iterator it = collection.iterator(); 168 while (it.hasNext()) { 169 ListItem item = addItem(); 170 item.setValue(it.next()); 171 } 172 } 173 } 174 175 public Object getValue() { 176 Collection collection = createOrClearCollection(); 177 Iterator it = items.getElements().iterator(); 178 while (it.hasNext()) { 179 ListItem item = (ListItem) it.next(); 180 if (item.getElement().getValue() != null) { 181 Object value = item.getElement().getValue(); 182 if (parentProperty != null) { 183 PropertyUtils.setProperty(value, parentProperty, 184 getEditorBinding().getEditorBinder().getBackingObject()); 185 } 186 collection.add(value); 187 } 188 } 189 return collection; 190 } 191 192 private Collection createOrClearCollection() { 193 Collection collection = (Collection ) getEditorBinding().getValue(); 194 if (collection == null) { 195 collection = (Collection ) BeanUtils.instantiateClass(collectionClass); 196 } 197 else { 198 collection.clear(); 199 } 200 return collection; 201 } 202 203 protected ListItem addItem() { 204 ListItem item = new ListItem(); 205 items.addElement(item); 206 item.focus(); 207 208 item.setValue(null); 209 210 return item; 211 } 212 213 protected void removeItem(ListItem item) { 214 items.removeElement(item); 215 } 216 217 protected void validate() { 218 int size = ((Collection ) getValue()).size(); 219 if (minSize > 0 && size < minSize) { 220 ErrorUtils.reject(this, "list.size.tooSmall", 221 new Object [] {new Integer (minSize)}); 222 } 223 if (maxSize > 0 && size > maxSize) { 224 ErrorUtils.reject(this, "list.size.tooLarge", 225 new Object [] {new Integer (maxSize)}); 226 } 227 } 228 229 public Container getItems() { 230 return this.items; 231 } 232 233 public String getInitScript() { 234 if (sortable && !items.isEmpty()) { 235 return TemplateUtils.getInitScript(this); 236 } 237 else { 238 return null; 239 } 240 } 241 242 protected void processRequestInternal(FormRequest request) { 243 if (sortable) { 244 String itemOrder = request.getParameter(getParamName()); 245 if (StringUtils.hasLength(itemOrder)) { 246 Collections.sort(items.getElements(), 247 new ListItemComparator(itemOrder)); 248 } 249 } 250 } 251 252 public class ListItem extends TemplateElement implements DHTMLElement { 253 254 private Editor element; 255 256 private Button removeButton; 257 258 public ListItem() { 259 super("item"); 260 setSurroundBySpan(false); 261 element = (Editor) itemElementFactory.createElement(this, getForm()); 262 element.setRequired(true); 263 removeButton = new Button(); 264 removeButton.setLabelKey("label.form.list.remove"); 265 removeButton.setLabel("Remove"); 266 removeButton.setTabIndex(2); 267 removeButton.addClickListener(new ClickListener() { 268 public void clicked(ClickEvent event) { 269 removeItem(ListItem.this); 270 } 271 }); 272 addComponent("element", element); 273 addComponent("removeButton", removeButton); 274 } 275 276 public Editor getElement() { 277 return element; 278 } 279 280 public void focus() { 281 element.focus(); 282 } 283 284 public boolean isShowDragHandle() { 285 return isSortable(); 286 } 287 288 public void setValue(Object value) { 289 element.setEditorBinding(new CollectionItemEditorBinding(element, value)); 290 element.setValue(value); 291 } 292 293 public String getInitScript() { 294 if (getForm().isRendering()) { 295 return null; 296 } 297 return ListEditor.this.getInitScript(); 298 } 299 300 } 301 302 private class ListItemComparator implements Comparator { 303 304 private String itemOrder; 305 306 public ListItemComparator(String itemOrder) { 307 this.itemOrder = itemOrder; 308 } 309 310 public int compare(Object obj1, Object obj2) { 311 ListItem item1 = (ListItem) obj1; 312 ListItem item2 = (ListItem) obj2; 313 int pos1 = itemOrder.indexOf(item1.getId() + ','); 314 int pos2 = itemOrder.indexOf(item2.getId() + ','); 315 return pos1 - pos2; 316 } 317 318 } 319 } 320 | Popular Tags |