001: /* BaseListbox.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Aug 8, 2007 5:48:27 PM 2007, Created by Dennis.Chen
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.jsf.zul.impl;
020:
021: import java.util.Collection;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import javax.faces.context.FacesContext;
028:
029: import org.zkoss.jsf.zul.impl.BranchInput;
030: import org.zkoss.zk.ui.Component;
031: import org.zkoss.zk.ui.event.Event;
032: import org.zkoss.zk.ui.event.EventListener;
033: import org.zkoss.zk.ui.event.Events;
034: import org.zkoss.zul.Tree;
035: import org.zkoss.zul.TreeModel;
036: import org.zkoss.zul.Treechildren;
037: import org.zkoss.zul.Treeitem;
038:
039: /**
040: * The Base implementation of Tree.
041: * This component should be declared nested under {@link org.zkoss.jsf.zul.Page}.
042: * @author Dennis.Chen
043: *
044: */
045: abstract public class BaseTree extends BranchInput {
046:
047: /**
048: * Override , and return null, It means that do not map value of ValueHolder to zul component. i
049: * will take case value of ValueHolder to selecteItem of tree
050: * @return null
051: */
052: public String getMappedAttributeName() {
053: return null;
054: }
055:
056: protected void afterZULComponentComposed(Component zulcomp) {
057: super .afterZULComponentComposed(zulcomp);
058:
059: if (isLocalValueSet() || getValueBinding("value") != null) {
060:
061: zulcomp.addEventListener("onProcessZULJSFSelection",
062: new ProcessSelection());
063:
064: //send onProcessZULJSFSelection as late as possible.
065: Events.postEvent("onProcessZULJSFSelection", zulcomp,
066: getValue());
067: }
068: }
069:
070: private class ProcessSelection implements EventListener {
071: public void onEvent(Event event) throws Exception {
072: Tree tree = (Tree) event.getTarget();
073: Object value = event.getData();
074: processSelection(tree, value);
075: }
076: }
077:
078: /**
079: * set selected item of listbox by value,
080: */
081: private void processSelection(Tree tree, Object value) {
082: HashMap selections = new HashMap();
083: tree.clearSelection();
084:
085: Object multi = getAttributeValue("multiple");
086: boolean isMulti = (multi == null) ? false : "true"
087: .equalsIgnoreCase(multi.toString()) ? true : false;
088: if (value == null) {
089: return;
090: } else if (isMulti) {
091: if (value instanceof Collection) {
092: Iterator iter = ((Collection) value).iterator();
093: while (iter.hasNext()) {
094: selections.put(iter.next(), "");
095: }
096: } else if (value instanceof Object[]) {
097: Object[] s = (Object[]) value;
098: for (int i = 0; i < s.length; i++) {
099: selections.put(s[i], "");
100: }
101: } else {
102: selections.put(value, "");
103: }
104: } else {
105: selections.put(value, "");
106: }
107: //go through all tree to make selection
108:
109: TreeModel model = tree.getModel();
110:
111: if (model == null) {
112: Treechildren tc = tree.getTreechildren();
113: if (tc != null && !selections.isEmpty()) {
114: dfSearchAndSelect(tree, tc.getChildren(), selections,
115: isMulti);
116: }
117: } else {
118: Object root = model.getRoot();
119: dfSearchAndSelect(tree, root, root, model, selections,
120: isMulti);
121: }
122:
123: }
124:
125: /**
126: * a recursive deep first search for search and select tree item by value in selections
127: * @param tree the tree instance
128: * @param root the root object of model
129: * @param parent the parent object to search
130: * @param model the tree model
131: * @param selections a Hashmap of selection
132: * @param isMulti true if is multiple selections
133: * @return true if skip search
134: */
135: private boolean dfSearchAndSelect(final Tree tree,
136: final Object root, final Object parent,
137: final TreeModel model, final HashMap selections,
138: final boolean isMulti) {
139: if (parent == null) {
140: return false;
141: }
142:
143: Object child = null;
144: int size = model.getChildCount(parent);
145: for (int i = 0; i < size; i++) {
146: child = model.getChild(parent, i);
147: if (child != null && selections.get(child) != null) {
148: //hit selection.
149: int[] path = model.getPath(root, child);
150: Treeitem ti = tree.renderItemByPath(path);
151: if (ti != null) {
152: tree.addItemToSelection(ti);
153: }
154:
155: selections.remove(child);
156: if (!isMulti || selections.isEmpty()) {
157: return true;
158: }
159: }
160:
161: boolean skip = dfSearchAndSelect(tree, root, child, model,
162: selections, isMulti);
163: if (skip) {
164: return true;
165: }
166: }
167: return false;
168:
169: }
170:
171: /**
172: * a recursive deep for search and select tree item by value in selections
173: * @param tree the tree instance
174: * @param children a List of Treeitem
175: * @param selections a Hashmap of selection
176: * @param isMulti true if is multiple selections
177: * @return return true if skip search
178: */
179: private boolean dfSearchAndSelect(final Tree tree,
180: final List children, final HashMap selections,
181: final boolean isMulti) {
182: if (children == null) {
183: return false;
184: }
185:
186: Object data = null;
187: for (Iterator iter = children.iterator(); iter.hasNext();) {
188: Treeitem ti = (Treeitem) iter.next();
189: data = ti.getValue();
190: if (data != null && selections.get(data) != null) {
191: //hit selection.
192: tree.addItemToSelection(ti);
193: selections.remove(data);
194: if (!isMulti || selections.isEmpty()) {
195: return true;
196: }
197: }
198:
199: Treechildren tc = ti.getTreechildren();
200: if (tc != null && !selections.isEmpty()) {
201: boolean skip = dfSearchAndSelect(tree,
202: tc.getChildren(), selections, isMulti);
203: if (skip) {
204: return true;
205: }
206: }
207:
208: }
209: return false;
210: }
211:
212: /**
213: * decode parameter in request,
214: * @param context
215: */
216: protected void clientInputDecode(FacesContext context) {
217: String clientId = this .getClientId(context);
218: Map requestMap = context.getExternalContext()
219: .getRequestParameterMap();
220: if (requestMap.containsKey(clientId)) {
221:
222: String[] newValue = (String[]) context.getExternalContext()
223: .getRequestParameterValuesMap().get(clientId);
224:
225: Object multi = getAttributeValue("multiple");
226: boolean isMulti = (multi == null) ? false : "true"
227: .equalsIgnoreCase(multi.toString()) ? true : false;
228:
229: if (newValue != null) {
230: if (newValue.length > 0) {
231: //JDK 1.5 BUG ? 5043241 on , incompatible types for ?: neither is a subtype of the other
232: //setSubmittedValue(isMulti?newValue:newValue[0]);
233: Object value;
234: if (isMulti) {
235: value = newValue;
236: } else {
237: value = newValue[0];
238: }
239: setSubmittedValue(value);
240: }
241: }
242: }
243: }
244:
245: }
|