Author: nbelaevski
Date: 2010-10-29 15:15:30 -0400 (Fri, 29 Oct 2010)
New Revision: 19790
Added:
sandbox/trunk/ui/tree-actual/api/src/main/java/org/
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleListener.java
sandbox/trunk/ui/tree-actual/pom.xml
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
Modified:
sandbox/trunk/ui/tree-actual/ui/
sandbox/trunk/ui/tree-actual/ui/pom.xml
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTree.java
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
Log:
https://jira.jboss.org/browse/RF-9315
Added:
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
===================================================================
---
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
(rev 0)
+++
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleEvent.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TreeToggleEvent extends FacesEvent {
+
+ private static final long serialVersionUID = -7264894390585192069L;
+
+ private boolean expanded;
+
+ public TreeToggleEvent(UIComponent component, boolean expanded) {
+ super(component);
+
+ this.expanded = expanded;
+ }
+
+ public boolean isExpanded() {
+ return expanded;
+ }
+
+ public boolean isCollapsed() {
+ return !isExpanded();
+ }
+
+ @Override
+ public boolean isAppropriateListener(FacesListener listener) {
+ return listener instanceof TreeToggleListener;
+ }
+
+ @Override
+ public void processListener(FacesListener listener) {
+ ((TreeToggleListener) listener).processToggle(this);
+ }
+
+}
Added:
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleListener.java
===================================================================
---
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleListener.java
(rev 0)
+++
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleListener.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.event;
+
+import javax.faces.event.FacesListener;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface TreeToggleListener extends FacesListener {
+
+ public void processToggle(TreeToggleEvent event);
+
+}
Added: sandbox/trunk/ui/tree-actual/pom.xml
===================================================================
--- sandbox/trunk/ui/tree-actual/pom.xml (rev 0)
+++ sandbox/trunk/ui/tree-actual/pom.xml 2010-10-29 19:15:30 UTC (rev 19790)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source Copyright 2010, Red Hat,
+ Inc. and individual contributors by the @authors tag. See the
+ copyright.txt in the distribution for a full listing of
+ individual contributors. This is free software; you can
+ redistribute it and/or modify it under the terms of the GNU
+ Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your
+ option) any later version. This software is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ for more details. You should have received a copy of the GNU
+ Lesser General Public License along with this software; if not,
+ write to the Free Software Foundation, Inc., 51 Franklin St,
+ Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site:
+
http://www.fsf.org.
+-->
+
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.richfaces</groupId>
+ <artifactId>richfaces-root-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.richfaces.ui.iteration</groupId>
+ <artifactId>richfaces-ui-tree-aggregator</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Richfaces UI Components: Tree Aggregator</name>
+
+ <modules>
+ <module>api</module>
+ <module>ui</module>
+ </modules>
+
+</project>
\ No newline at end of file
Property changes on: sandbox/trunk/ui/tree-actual/ui
___________________________________________________________________
Name: svn:ignore
+ bin
Modified: sandbox/trunk/ui/tree-actual/ui/pom.xml
===================================================================
--- sandbox/trunk/ui/tree-actual/ui/pom.xml 2010-10-29 16:45:44 UTC (rev 19789)
+++ sandbox/trunk/ui/tree-actual/ui/pom.xml 2010-10-29 19:15:30 UTC (rev 19790)
@@ -42,6 +42,11 @@
</dependency>
<dependency>
<groupId>org.richfaces.ui.iteration</groupId>
+ <artifactId>tree-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.ui.iteration</groupId>
<artifactId>richfaces-ui-iteration-api</artifactId>
</dependency>
<dependency>
Modified:
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTree.java
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-10-29
16:45:44 UTC (rev 19789)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -22,18 +22,34 @@
package org.richfaces.component;
import java.util.Iterator;
+import java.util.Map;
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
+import javax.faces.component.UpdateModelException;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ExceptionQueuedEvent;
+import javax.faces.event.ExceptionQueuedEventContext;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.PhaseId;
import org.ajax4jsf.model.DataComponentState;
import org.ajax4jsf.model.ExtendedDataModel;
+import org.richfaces.application.MessageFactory;
+import org.richfaces.application.ServiceTracker;
+import org.richfaces.appplication.FacesMessages;
import org.richfaces.cdk.annotations.Attribute;
import org.richfaces.cdk.annotations.JsfComponent;
import org.richfaces.cdk.annotations.JsfRenderer;
import org.richfaces.cdk.annotations.Tag;
+import org.richfaces.component.util.MessageUtil;
import org.richfaces.convert.SequenceRowKeyConverter;
+import org.richfaces.event.TreeToggleEvent;
import org.richfaces.model.TreeDataModelImpl;
import com.google.common.base.Predicate;
@@ -52,7 +68,7 @@
public abstract class AbstractTree extends UIDataAdaptor {
public static final String COMPONENT_TYPE = "org.richfaces.Tree";
-
+
public static final String COMPONENT_FAMILY = "org.richfaces.Tree";
private static final Predicate<UIComponent> RENDERED_UITREE_NODE = new
Predicate<UIComponent>() {
@@ -60,15 +76,23 @@
return (input instanceof AbstractTreeNode) && input.isRendered();
};
};
-
+
private static final Converter ROW_KEY_CONVERTER = new SequenceRowKeyConverter();
+
+ private enum PropertyKeys {
+ expanded
+ }
+
+ private transient UIComponent decoderHelper = null;
public AbstractTree() {
setRendererType("org.richfaces.TreeRenderer");
}
public abstract Object getValue();
-
+
+ public abstract boolean isImmediate();
+
@Override
public String getFamily() {
return COMPONENT_FAMILY;
@@ -76,7 +100,37 @@
@Attribute(defaultValue = "SwitchType.DEFAULT")
public abstract SwitchType getToggleMode();
-
+
+ @SuppressWarnings("unchecked")
+ protected Boolean getLocalExpandedValue(FacesContext facesContext) {
+ Map<String, Object> stateMap = (Map<String, Object>)
getStateHelper().get(PropertyKeys.expanded);
+ if (stateMap == null) {
+ return null;
+ }
+
+ String key = this.getClientId(facesContext);
+ return (Boolean) stateMap.get(key);
+ }
+
+ public boolean isExpanded() {
+ FacesContext context = getFacesContext();
+ Boolean localExpandedValue = getLocalExpandedValue(context);
+ if (localExpandedValue != null) {
+ return localExpandedValue.booleanValue();
+ }
+
+ ValueExpression ve = getValueExpression(PropertyKeys.expanded.toString());
+ if (ve != null) {
+ return Boolean.TRUE.equals(ve.getValue(context.getELContext()));
+ }
+
+ return false;
+ }
+
+ public void setExpanded(boolean newValue) {
+ getStateHelper().put(PropertyKeys.expanded, this.getClientId(getFacesContext()),
newValue);
+ }
+
/* (non-Javadoc)
* @see org.richfaces.component.UIDataAdaptor#createExtendedDataModel()
*/
@@ -108,18 +162,96 @@
public Iterator<Object> getChildrenIterator(FacesContext faces, Object rowKey)
{
return ((TreeDataModelImpl) getExtendedDataModel()).getChildrenIterator(faces,
rowKey);
}
-
+
public AbstractTreeNode getTreeNodeComponent() {
if (getChildCount() == 0) {
return null;
}
-
+
Iterator<UIComponent> iterator = Iterators.filter(getChildren().iterator(),
RENDERED_UITREE_NODE);
if (iterator.hasNext()) {
return (AbstractTreeNode) iterator.next();
}
-
+
return null;
}
+
+ @Override
+ public void broadcast(FacesEvent event) throws AbortProcessingException {
+ super.broadcast(event);
+
+ if (event instanceof TreeToggleEvent) {
+ TreeToggleEvent toggleEvent = (TreeToggleEvent) event;
+ boolean newExpandedValue = toggleEvent.isExpanded();
+
+ FacesContext context = getFacesContext();
+ ValueExpression expression =
getValueExpression(PropertyKeys.expanded.toString());
+ if (expression != null) {
+ ELContext elContext = context.getELContext();
+ Exception caught = null;
+ FacesMessage message = null;
+ try {
+ expression.setValue(elContext, newExpandedValue);
+ } catch (ELException e) {
+ caught = e;
+ String messageStr = e.getMessage();
+ Throwable result = e.getCause();
+ while (null != result &&
+ result.getClass().isAssignableFrom(ELException.class)) {
+ messageStr = result.getMessage();
+ result = result.getCause();
+ }
+ if (null == messageStr) {
+ MessageFactory messageFactory =
ServiceTracker.getService(MessageFactory.class);
+ message =
+ messageFactory.createMessage(context,
FacesMessages.UIINPUT_UPDATE,
+ MessageUtil.getLabel(context, this));
+ } else {
+ message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
+ messageStr,
+ messageStr);
+ }
+ } catch (Exception e) {
+ caught = e;
+ MessageFactory messageFactory =
ServiceTracker.getService(MessageFactory.class);
+ message =
+ messageFactory.createMessage(context,
FacesMessages.UIINPUT_UPDATE,
+ MessageUtil.getLabel(context, this));
+ }
+ if (caught != null) {
+ assert(message != null);
+ UpdateModelException toQueue = new UpdateModelException(message,
caught);
+ ExceptionQueuedEventContext eventContext =
+ new ExceptionQueuedEventContext(context,
+ toQueue,
+ this,
+ PhaseId.UPDATE_MODEL_VALUES);
+ context.getApplication().publishEvent(context,
+ ExceptionQueuedEvent.class,
+ eventContext);
+ }
+ } else {
+ setExpanded(newExpandedValue);
+ }
+ }
+ }
+ @Override
+ public void decode(FacesContext context) {
+ try {
+ decoderHelper = new TreeDecoderHelper(this);
+ super.decode(context);
+ } finally {
+ decoderHelper = null;
+ }
+ }
+
+ @Override
+ protected Iterator<UIComponent> dataChildren() {
+ if (decoderHelper != null) {
+ return Iterators.concat(super.dataChildren(),
Iterators.<UIComponent>singletonIterator(decoderHelper));
+ } else {
+ return super.dataChildren();
+ }
+ }
}
Modified:
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java 2010-10-29
16:45:44 UTC (rev 19789)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -21,11 +21,17 @@
*/
package org.richfaces.component;
+import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.PhaseId;
+import org.richfaces.cdk.annotations.Attribute;
import org.richfaces.cdk.annotations.JsfComponent;
import org.richfaces.cdk.annotations.JsfRenderer;
import org.richfaces.cdk.annotations.Tag;
+import org.richfaces.event.TreeToggleEvent;
/**
* @author Nick Belaevski
@@ -51,4 +57,38 @@
public String getFamily() {
return COMPONENT_FAMILY;
}
+
+ @Attribute(defaultValue = "findTreeComponent().isImmediate()")
+ public abstract boolean isImmediate();
+
+ protected AbstractTree findTreeComponent() {
+ UIComponent c = this;
+ while (c != null && !(c instanceof AbstractTree)) {
+ c = c.getParent();
+ }
+
+ return (AbstractTree) c;
+ }
+
+ @Override
+ public void queueEvent(FacesEvent event) {
+ if (this.equals(event.getComponent())) {
+ if (event instanceof TreeToggleEvent) {
+ PhaseId targetPhase = isImmediate() ? PhaseId.APPLY_REQUEST_VALUES :
PhaseId.PROCESS_VALIDATIONS;
+ event.setPhaseId(targetPhase);
+ }
+ }
+
+ super.queueEvent(event);
+ }
+
+ @Override
+ public void broadcast(FacesEvent event) throws AbortProcessingException {
+ super.broadcast(event);
+
+ if (event instanceof TreeToggleEvent) {
+ TreeToggleEvent toggleEvent = (TreeToggleEvent) event;
+ new TreeToggleEvent(findTreeComponent(), toggleEvent.isExpanded()).queue();
+ }
+ }
}
Added:
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
(rev 0)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.component;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class TreeDecoderHelper extends UIComponentBase {
+
+ public static final String HELPER_ID = "__treeDecoderHelper";
+
+ private AbstractTree tree;
+
+ public TreeDecoderHelper(AbstractTree tree) {
+ super();
+ this.tree = tree;
+ setId(HELPER_ID);
+ setTransient(true);
+ }
+
+ @Override
+ public boolean isInView() {
+ return tree.isInView();
+ }
+
+ @Override
+ public boolean isRendered() {
+ return tree.isRendered();
+ }
+
+ @Override
+ public String getFamily() {
+ return null;
+ }
+
+ @Override
+ public UIComponent getParent() {
+ return tree;
+ }
+
+}
Modified:
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java 2010-10-29
16:45:44 UTC (rev 19789)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -166,13 +166,26 @@
return new SequenceRowKeyIterator<TreeNode>(sequenceKey, itr);
}
+ protected void walk(FacesContext context, DataVisitor visitor, Range range, Object
argument, Iterator<Object> keysIterator) {
+ while (keysIterator.hasNext()) {
+ Object object = (Object) keysIterator.next();
+
+ visitor.process(context, object, argument);
+
+ Iterator<Object> childrenIterator = getChildrenIterator(context,
object);
+ walk(context, visitor, range, argument, childrenIterator);
+ }
+ }
+
/* (non-Javadoc)
* @see org.ajax4jsf.model.ExtendedDataModel#walk(javax.faces.context.FacesContext,
org.ajax4jsf.model.DataVisitor, org.ajax4jsf.model.Range, java.lang.Object)
*/
@Override
public void walk(FacesContext context, DataVisitor visitor, Range range, Object
argument) {
// TODO Auto-generated method stub
-
+
+ Iterator<Object> iterator = getChildrenIterator(context, null);
+ walk(context, visitor, range, argument, iterator);
}
}
Modified:
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java 2010-10-29
16:45:44 UTC (rev 19789)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java 2010-10-29
19:15:30 UTC (rev 19790)
@@ -26,18 +26,29 @@
import static org.richfaces.renderkit.util.AjaxRendererUtils.buildEventOptions;
import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.Map;
import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.javascript.JSReference;
import org.richfaces.component.AbstractTree;
+import org.richfaces.component.AbstractTreeNode;
import org.richfaces.component.SwitchType;
+import org.richfaces.component.TreeDecoderHelper;
import org.richfaces.component.util.HtmlUtil;
+import org.richfaces.event.TreeToggleEvent;
import org.richfaces.log.Logger;
import org.richfaces.log.RichfacesLogger;
@@ -53,14 +64,20 @@
private static final Logger LOGGER = RichfacesLogger.RENDERKIT.getLogger();
- private static final String NODE_ID = "nodeId";
+ private static final String TOGGLE_DATA = "toggleData";
- private static final String NEW_STATE = "newState";
+ private static final String TREE_TOGGLE_ID_PARAM =
"org.richfaces.Tree.TREE_TOGGLE_ID";
+
+ private static final String NODE_TOGGLE_ID_PARAM =
"org.richfaces.Tree.NODE_TOGGLE_ID";
- private static final String TOGGLE_ID_PARAM =
"org.richfaces.Tree.TOGGLE_ID";
-
private static final String NEW_STATE_PARAM =
"org.richfaces.Tree.NEW_STATE";
+
+ private static final JSReference JS_TREE_ID = new JSReference(TOGGLE_DATA +
".treeId");
+ private static final JSReference JS_NODE_ID = new JSReference(TOGGLE_DATA +
".nodeId");
+
+ private static final JSReference JS_NEW_STATE = new JSReference(TOGGLE_DATA +
".treeId");
+
private static final class QueuedData {
private Object rowKey;
@@ -206,8 +223,9 @@
JSFunction ajaxFunction = buildAjaxFunction(context, component,
AJAX_FUNCTION_NAME);
AjaxEventOptions eventOptions = buildEventOptions(context, component);
- eventOptions.setParameter(TOGGLE_ID_PARAM, new JSReference(NODE_ID));
- eventOptions.setParameter(NEW_STATE_PARAM, new JSReference(NEW_STATE));
+ eventOptions.setParameter(TREE_TOGGLE_ID_PARAM, JS_TREE_ID);
+ eventOptions.setParameter(NODE_TOGGLE_ID_PARAM, JS_NODE_ID);
+ eventOptions.setParameter(NEW_STATE_PARAM, JS_NEW_STATE);
if (!eventOptions.isEmpty()) {
ajaxFunction.addParameter(eventOptions);
@@ -215,4 +233,40 @@
return ajaxFunction.toScript();
}
+
+ @Override
+ protected void doDecode(FacesContext context, UIComponent component) {
+ super.doDecode(context, component);
+
+ final Map<String, String> map =
context.getExternalContext().getRequestParameterMap();
+ String toggleId = map.get(TREE_TOGGLE_ID_PARAM);
+ if (component.getClientId(context).equals(toggleId)) {
+
+ String nodeId = map.get(NODE_TOGGLE_ID_PARAM) +
UINamingContainer.getSeparatorChar(context)
+ + TreeDecoderHelper.HELPER_ID;
+
+ VisitContext visitContext = createVisitContext(context, nodeId);
+ component.visitTree(visitContext, new VisitCallback() {
+
+ public VisitResult visit(VisitContext context, UIComponent target) {
+ AbstractTree tree = (AbstractTree) target.getParent();
+ AbstractTreeNode treeNode = tree.getTreeNodeComponent();
+ if (treeNode != null) {
+ boolean expanded = Boolean.valueOf(map.get(NEW_STATE_PARAM));
+ if (tree.isExpanded() ^ expanded) {
+ new TreeToggleEvent(treeNode, expanded);
+ }
+ }
+
+ return VisitResult.COMPLETE;
+ }
+ });
+
+ }
+ }
+
+ private VisitContext createVisitContext(FacesContext context, String nodeId) {
+ return VisitContext.createVisitContext(context, Collections.singleton(nodeId),
+ EnumSet.<VisitHint>of(VisitHint.SKIP_UNRENDERED));
+ }
}
Modified:
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
===================================================================
---
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js 2010-10-29
16:45:44 UTC (rev 19789)
+++
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js 2010-10-29
19:15:30 UTC (rev 19790)
@@ -28,6 +28,10 @@
});
}
+ var TREE_HANDLE_CLASSES = ["tree_collapse", "tree_expand"];
+
+ var TREE_CLASSES = ["tree_handle_collapsed",
"tree_handle_expanded"];
+
richfaces.ui = richfaces.ui || {};
richfaces.ui.TreeNode = richfaces.BaseComponent.extendClass({
@@ -113,18 +117,24 @@
}
},
- collapse: function() {
+ __changeToggleState: function(newState) {
if (!this.isLeaf()) {
var tree = this.getTree();
switch (tree.getToggleMode()) {
case 'client':
- this.elt.addClass("tree_collapse");
- this.handler.addClass("tree_handle_collapsed").removeClass("tree_handle_expanded");
+ this.elt.addClass(TREE_HANDLE_CLASSES[newState ? 1 :
0]).removeClass(TREE_HANDLE_CLASSES[!newState ? 1 : 0]);
+ this.handler.addClass(TREE_CLASSES[newState ? 1 :
0]).removeClass(TREE_CLASSES[!newState ? 1 : 0]);
break;
case 'ajax':
- tree.toggleByAjax(null, richfaces.getDomElement(this.id).id, false);
+ var toggleData = {
+ nodeId: richfaces.getDomElement(this.id).id,
+ newState: newState
+ };
+
+ //TODO - event?
+ tree.toggleByAjax(null, toggleData);
break;
case 'server':
@@ -134,26 +144,13 @@
}
},
+
+ collapse: function() {
+ this.__changeToggleState(false);
+ },
expand: function() {
- if (!this.isLeaf()) {
- var tree = this.getTree();
-
- switch (tree.getToggleMode()) {
- case 'client':
- this.elt.removeClass("tree_collapse");
- this.handler.removeClass("tree_handle_collapsed").addClass("tree_handle_expanded");
- break;
-
- case 'ajax':
- tree.toggleByAjax(null, richfaces.getDomElement(this.id).id, true);
- break;
-
- case 'server':
-
- break;
- }
- }
+ this.__changeToggleState(true);
},
getTree: function() {
@@ -187,7 +184,7 @@
this.__selectionMode = options.selectionMode || 'ajax';
if (options.ajaxToggler) {
- this.__ajaxToggler = new Function("event", "nodeId",
"newState", options.ajaxToggler);
+ this.__ajaxToggler = new Function("event", "toggleData",
options.ajaxToggler);
}
},
@@ -197,8 +194,9 @@
this.__ajaxToggler = null;
},
- toggleByAjax: function(event, nodeId, newState) {
- this.__ajaxToggler(event, nodeId, newState);
+ toggleByAjax: function(event, toggleData) {
+ toggleData.treeId = this.id;
+ this.__ajaxToggler(event, toggleData);
},
getToggleMode: function() {