001: /* BindingComboitemRenderer.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Jan 3, 2008 10:54:54 AM , Created by jumperchen
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zkplus.databind;
020:
021: import java.io.Serializable;
022: import java.util.ArrayList;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027:
028: import org.zkoss.zk.ui.Component;
029: import org.zkoss.zk.ui.sys.ComponentsCtrl;
030: import org.zkoss.zul.Combobox;
031: import org.zkoss.zul.Comboitem;
032: import org.zkoss.zul.Grid;
033: import org.zkoss.zul.Listbox;
034:
035: /**
036: * @author jumperchen
037: * @since 3.0.2
038: */
039: /*package*/class BindingComboitemRenderer implements
040: org.zkoss.zul.ComboitemRenderer,
041: org.zkoss.zul.ComboitemRendererExt, Serializable {
042: private static final String KIDS = "zkplus.databind.KIDS";
043: private Comboitem _template;
044: private DataBinder _binder;
045: private int x = 0;
046:
047: public BindingComboitemRenderer(Comboitem template,
048: DataBinder binder) {
049: _template = template;
050: _binder = binder;
051: }
052:
053: //link cloned components with bindings of templates
054: private void linkTemplates(Component clone, Component template,
055: Map templatemap) {
056: if (_binder.existsBindings(template)) {
057: templatemap.put(template, clone);
058: clone.setAttribute(_binder.TEMPLATEMAP, templatemap);
059: clone.setAttribute(_binder.TEMPLATE, template);
060: }
061:
062: //Combobox in Listbox, Combobox in Grid no need to process
063: if (template instanceof Grid || template instanceof Listbox) {
064: return;
065: }
066:
067: final Iterator itt = template.getChildren().iterator();
068: final Iterator itc = clone.getChildren().iterator();
069: while (itt.hasNext()) {
070: final Component t = (Component) itt.next();
071: final Component c = (Component) itc.next();
072: linkTemplates(c, t, templatemap); //recursive
073: }
074: }
075:
076: //setup id of cloned components (cannot called until the component is attached to Listbox)
077: private void setupCloneIds(Component clone) {
078: //bug #1813271: Data binding generates duplicate ids in grids/listboxes
079: clone.setId("@" + clone.getUuid() + x++); //init id to @uuid to avoid duplicate id issue
080:
081: //Combobox in Listbox, Combobox in Grid no need to process
082: if (clone instanceof Grid || clone instanceof Listbox) {
083: return;
084: }
085:
086: for (final Iterator it = clone.getChildren().iterator(); it
087: .hasNext();) {
088: setupCloneIds((Component) it.next()); //recursive
089: }
090: }
091:
092: public void render(Comboitem item, Object bean) throws Exception {
093: final List kids = (List) item.getAttribute(KIDS);
094: item.getChildren().addAll(kids);
095: //item.removeAttribute(KIDS);
096:
097: //remove template mark of cloned component and its decendant
098: _binder.setupTemplateComponent(item, null);
099:
100: //setup clone id
101: setupCloneIds(item);
102:
103: //bind bean to the associated listitem and its decendant
104: final String varname = (String) _template
105: .getAttribute(_binder.VARNAME);
106: final Map templatemap = (Map) item
107: .getAttribute(_binder.TEMPLATEMAP);
108: templatemap.put(varname, bean);
109:
110: //apply the data binding
111: _binder.loadComponent(item);
112: }
113:
114: public Comboitem newComboitem(Combobox combobox) {
115: //clone from template
116: final Comboitem clone = (Comboitem) _template.clone();
117: //TODO: see if databinder has this kind of Comboitem, if not, add new CollectionListItem
118: //avoid duplicate id error, will set to new id when render()
119: if (!ComponentsCtrl.isAutoId(clone.getId())) {
120: clone.setId("@" + clone.getUuid() + x++);
121: }
122:
123: //link cloned component with template
124: //each Comboitem and and it decendants share the same templatemap
125: Map templatemap = new HashMap(7);
126: linkTemplates(clone, _template, templatemap);
127:
128: //link this template map to parent templatemap (Combobox in Combobox)
129: Map parenttemplatemap = (Map) combobox
130: .getAttribute(_binder.TEMPLATEMAP);
131: if (parenttemplatemap != null) {
132: templatemap.put(_binder.TEMPLATEMAP, parenttemplatemap);
133: }
134: //kept clone kids somewhere to avoid create too many components in browser
135: final List kids = new ArrayList(clone.getChildren());
136: clone.setAttribute(KIDS, kids);
137: clone.getChildren().clear();
138: return clone;
139: }
140: }
|