View Javadoc

1   /*
2    * Ext GWT 2.2.5 - Ext for GWT
3    * Copyright(c) 2007-2010, Ext JS, LLC.
4    * licensing@extjs.com
5    * 
6    * http://extjs.com/license
7    */
8   package com.extjs.gxt.ui.client.widget.form;
9   
10  import java.util.List;
11  
12  import com.extjs.gxt.ui.client.core.El;
13  import com.extjs.gxt.ui.client.core.XTemplate;
14  import com.extjs.gxt.ui.client.data.ModelData;
15  import com.extjs.gxt.ui.client.event.ComponentEvent;
16  import com.extjs.gxt.ui.client.event.Events;
17  import com.extjs.gxt.ui.client.event.Listener;
18  import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
19  import com.extjs.gxt.ui.client.event.SelectionChangedListener;
20  import com.extjs.gxt.ui.client.event.SelectionProvider;
21  import com.extjs.gxt.ui.client.store.ListStore;
22  import com.extjs.gxt.ui.client.util.Size;
23  import com.extjs.gxt.ui.client.widget.ComponentHelper;
24  import com.extjs.gxt.ui.client.widget.ListView;
25  import com.google.gwt.dom.client.Document;
26  import com.google.gwt.user.client.DOM;
27  import com.google.gwt.user.client.Element;
28  import com.google.gwt.user.client.Event;
29  
30  /**
31   * A multi-select list field.
32   * 
33   * <dl>
34   * <dt>Inherited Events:</dt>
35   * <dd>Field Focus</dd>
36   * <dd>Field Blur</dd>
37   * <dd>Field Change</dd>
38   * <dd>Field Invalid</dd>
39   * <dd>Field Valid</dd>
40   * <dd>Field KeyPress</dd>
41   * <dd>Field SpecialKey</dd>
42   * <dd>BoxComponent Move</dd>
43   * <dd>BoxComponent Resize</dd>
44   * <dd>Component Enable</dd>
45   * <dd>Component Disable</dd>
46   * <dd>Component BeforeHide</dd>
47   * <dd>Component Hide</dd>
48   * <dd>Component BeforeShow</dd>
49   * <dd>Component Show</dd>
50   * <dd>Component Attach</dd>
51   * <dd>Component Detach</dd>
52   * <dd>Component BeforeRender</dd>
53   * <dd>Component Render</dd>
54   * <dd>Component BrowserEvent</dd>
55   * <dd>Component BeforeStateRestore</dd>
56   * <dd>Component StateRestore</dd>
57   * <dd>Component BeforeStateSave</dd>
58   * <dd>Component SaveState</dd>
59   * </dl>
60   * 
61   * @param <D> the model type
62   */
63  public class ListField<D extends ModelData> extends Field<D> implements SelectionProvider<D> {
64  
65    protected ListView<D> listView;
66    protected ListStore<D> store;
67  
68    private XTemplate template;
69    private String listStyle = "x-combo-list";
70    private String selectedStyle = "x-combo-selected";
71    private String itemSelector;
72    private El input;
73    private String valueField;
74  
75    public ListField() {
76      listView = new ListView<D>();
77      setSize(200, 100);
78      setPropertyEditor(new ListModelPropertyEditor<D>());
79    }
80  
81    public void addSelectionChangedListener(SelectionChangedListener<D> listener) {
82      listView.getSelectionModel().addListener(Events.SelectionChange, listener);
83    }
84  
85    @Override
86    public void disable() {
87      super.disable();
88      listView.disable();
89    }
90  
91    @Override
92    public void enable() {
93      super.enable();
94      listView.enable();
95    }
96  
97    /**
98     * Returns the display field.
99     * 
100    * @return the display field
101    */
102   public String getDisplayField() {
103     return getPropertyEditor().getDisplayProperty();
104   }
105 
106   /**
107    * Returns the item selector.
108    * 
109    * @return the item selector
110    */
111   public String getItemSelector() {
112     return itemSelector;
113   }
114 
115   /**
116    * Returns the field's list view.
117    * 
118    * @return the list view
119    */
120   public ListView<D> getListView() {
121     return listView;
122   }
123 
124   @Override
125   public ListModelPropertyEditor<D> getPropertyEditor() {
126     return (ListModelPropertyEditor<D>) propertyEditor;
127   }
128 
129   @Override
130   public String getRawValue() {
131     return "";
132   }
133 
134   public List<D> getSelection() {
135     return listView.getSelectionModel().getSelectedItems();
136   }
137 
138   /**
139    * Returns the field's store.
140    * 
141    * @return the store
142    */
143   public ListStore<D> getStore() {
144     return store;
145   }
146 
147   /**
148    * Returns the custom template.
149    * 
150    * @return the template
151    */
152   public XTemplate getTemplate() {
153     return template;
154   }
155 
156   @Override
157   public D getValue() {
158     List<D> sel = getSelection();
159     if (sel.size() > 0) {
160       return sel.get(0);
161     }
162     return null;
163   }
164 
165   public String getValueField() {
166     return valueField;
167   }
168 
169   public void removeSelectionListener(SelectionChangedListener<D> listener) {
170     listView.getSelectionModel().removeListener(Events.SelectionChange, listener);
171   }
172 
173   /**
174    * Sets the display field.
175    * 
176    * @param displayField the display field
177    */
178   public void setDisplayField(String displayField) {
179     getPropertyEditor().setDisplayProperty(displayField);
180   }
181 
182   /**
183    * This setting is required if a custom XTemplate has been specified.
184    * 
185    * @param itemSelector the item selector
186    */
187   public void setItemSelector(String itemSelector) {
188     this.itemSelector = itemSelector;
189   }
190 
191   @Override
192   public void setPropertyEditor(PropertyEditor<D> propertyEditor) {
193     assert propertyEditor instanceof ListModelPropertyEditor<?> : "PropertyEditor must be a ModelPropertyEditor instance";
194     super.setPropertyEditor(propertyEditor);
195   }
196 
197   public void setSelection(List<D> selection) {
198     if (selection != null && selection.size() > 0) {
199       super.setValue(selection.get(0));
200       listView.getSelectionModel().setSelection(selection);
201     } else {
202       super.setValue(null);
203       listView.getSelectionModel().deselectAll();
204     }
205   }
206 
207   @Override
208   public void setValue(D value) {
209     super.setValue(value);
210     listView.getSelectionModel().select(value, false);
211   }
212 
213   /**
214    * Sets the list field's list store.
215    * 
216    * @param store the store
217    */
218   public void setStore(ListStore<D> store) {
219     this.store = store;
220   }
221 
222   /**
223    * Sets the field's template used to render the list.
224    * 
225    * @param html the html frament
226    */
227   public void setTemplate(String html) {
228     assertPreRender();
229     template = XTemplate.create(html);
230   }
231 
232   /**
233    * Sets the field's template used to render the list.
234    * 
235    * @param template
236    */
237   public void setTemplate(XTemplate template) {
238     assertPreRender();
239     this.template = template;
240   }
241 
242   /**
243    * Sets the field's value field.
244    * 
245    * @param valueField the value field
246    */
247   public void setValueField(String valueField) {
248     this.valueField = valueField;
249   }
250 
251   @Override
252   protected void doAttachChildren() {
253     super.doAttachChildren();
254     ComponentHelper.doAttach(listView);
255   }
256 
257   @Override
258   protected void doDetachChildren() {
259     super.doDetachChildren();
260     ComponentHelper.doDetach(listView);
261   }
262 
263   @Override
264   protected El getInputEl() {
265     return input;
266   }
267 
268   @Override
269   protected void onFocus(ComponentEvent ce) {
270     super.onFocus(ce);
271     listView.focus();
272   }
273 
274   @Override
275   protected void onRender(Element parent, int index) {
276     setElement(DOM.createDiv(), parent, index);
277     addStyleName("x-form-list");
278 
279     input = new El((Element) Document.get().createHiddenInputElement().cast());
280     getElement().appendChild(input.dom);
281     if (template == null) {
282       String html = "<tpl for=\".\"><div class='x-combo-list-item' role='option'>{" + getDisplayField() + "}</div></tpl>";
283       template = XTemplate.create(html);
284     }
285     listView.setBorders(false);
286     listView.setTemplate(template);
287     listView.addStyleName(listStyle);
288     listView.setItemSelector(itemSelector != null ? itemSelector : ".x-combo-list-item");
289     listView.setStore(store);
290 
291     listView.setSelectStyle(selectedStyle);
292     listView.setOverStyle("x-combo-over");
293 
294     listView.getSelectionModel().addListener(Events.SelectionChange, new Listener<SelectionChangedEvent<D>>() {
295       public void handleEvent(SelectionChangedEvent<D> se) {
296         onSelectionChange(se.getSelection());
297       }
298     });
299 
300     listView.render(getElement());
301     listView.getAriaSupport().setRole("listbox");
302     ComponentHelper.setParent(this, listView);
303     disableTextSelection(true);
304     sinkEvents(Event.ONCLICK);
305 
306     super.onRender(parent, index);
307   }
308 
309   @Override
310   protected void onResize(int width, int height) {
311     super.onResize(width, height);
312     Size frameWidth = el().getFrameSize();
313     width -= frameWidth.width;
314     height -= frameWidth.height;
315     listView.setSize(width, height);
316   }
317 
318   protected void onSelectionChange(List<D> sel) {
319     String prop = valueField != null ? valueField : listView.getDisplayProperty();
320     StringBuffer sb = new StringBuffer();
321     for (D m : sel) {
322       sb.append(m.get(prop).toString());
323       sb.append(",");
324     }
325     String s = sb.toString();
326     if (sb.length() > 1) {
327       s = s.substring(0, s.length() - 1);
328     }
329     input.setValue(s);
330   }
331 
332   @Override
333   protected boolean validateValue(String value) {
334     return true;
335   }
336 
337 }