Author: nbelaevski
Date: 2010-11-01 11:43:05 -0400 (Mon, 01 Nov 2010)
New Revision: 19848
Added:
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionEvent.java
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionListener.java
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleListener.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKeyIterator.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderFull.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderPartial.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/last.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/leaf_icon.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/line.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/minus.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/node_icon.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/plus.gif
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.ecss
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
trunk/ui/iteration/ui/src/main/templates/tree.template.xml
trunk/ui/iteration/ui/src/main/templates/treeNode.template.xml
Modified:
trunk/examples/iteration-demo/src/main/webapp/tree.xhtml
trunk/ui/iteration/ui/src/main/resources/META-INF/richfaces/resource-mappings.properties
Log:
https://jira.jboss.org/browse/RF-9452
Modified: trunk/examples/iteration-demo/src/main/webapp/tree.xhtml
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/tree.xhtml 2010-11-01 15:40:40 UTC (rev
19847)
+++ trunk/examples/iteration-demo/src/main/webapp/tree.xhtml 2010-11-01 15:43:05 UTC (rev
19848)
@@ -3,7 +3,7 @@
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
-
xmlns:it="http://richfaces.org/tree">
+
xmlns:it="http://richfaces.org/iteration">
<f:view contentType="text/html" />
<h:head>
Copied: trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionEvent.java
(from rev 19809,
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeSelectionEvent.java)
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionEvent.java
(rev 0)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionEvent.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,67 @@
+/*
+ * 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 java.util.Collection;
+import java.util.HashSet;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TreeSelectionEvent extends FacesEvent {
+
+ private static final long serialVersionUID = 6292604445872458007L;
+
+ private Collection<Object> addedKeys = new HashSet<Object>();
+
+ private Collection<Object> removedKeys = new HashSet<Object>();
+
+ public TreeSelectionEvent(UIComponent component, Collection<Object> addedKeys,
Collection<Object> removedKeys) {
+ super(component);
+
+ this.addedKeys = addedKeys;
+ this.removedKeys = removedKeys;
+ }
+
+ @Override
+ public boolean isAppropriateListener(FacesListener listener) {
+ return listener instanceof TreeSelectionListener;
+ }
+
+ @Override
+ public void processListener(FacesListener listener) {
+ ((TreeSelectionListener) listener).processSelection(this);
+ }
+
+ public Collection<Object> getAddedKeys() {
+ return addedKeys;
+ }
+
+ public Collection<Object> getRemovedKeys() {
+ return removedKeys;
+ }
+}
Copied:
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionListener.java (from
rev 19809,
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeSelectionListener.java)
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionListener.java
(rev 0)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeSelectionListener.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -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 TreeSelectionListener extends FacesListener {
+
+ public void processSelection(TreeSelectionEvent event);
+
+}
Copied: trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
(from rev 19790,
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleEvent.java)
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleEvent.java
(rev 0)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleEvent.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -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);
+ }
+
+}
Copied: trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleListener.java
(from rev 19790,
sandbox/trunk/ui/tree-actual/api/src/main/java/org/richfaces/event/TreeToggleListener.java)
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleListener.java
(rev 0)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/event/TreeToggleListener.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -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);
+
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
(from rev 19837,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTree.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,413 @@
+/*
+ * 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 java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+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.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitResult;
+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.ajax4jsf.model.Range;
+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.context.ExtendedVisitContext;
+import org.richfaces.context.ExtendedVisitContextMode;
+import org.richfaces.convert.SequenceRowKeyConverter;
+import org.richfaces.event.TreeSelectionEvent;
+import org.richfaces.event.TreeSelectionListener;
+import org.richfaces.event.TreeToggleEvent;
+import org.richfaces.event.TreeToggleListener;
+import org.richfaces.model.TreeDataModelImpl;
+import org.richfaces.renderkit.MetaComponentRenderer;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+@JsfComponent(
+ type = AbstractTree.COMPONENT_TYPE,
+ family = AbstractTree.COMPONENT_FAMILY,
+ tag = @Tag(name = "tree"),
+ renderer = @JsfRenderer(type = "org.richfaces.TreeRenderer")
+)
+public abstract class AbstractTree extends UIDataAdaptor implements
MetaComponentResolver, MetaComponentEncoder {
+
+ public static final String COMPONENT_TYPE = "org.richfaces.Tree";
+
+ public static final String COMPONENT_FAMILY = "org.richfaces.Tree";
+
+ public static final String NODE_META_COMPONENT_ID = "node";
+
+ public static final String SELECTION_META_COMPONENT_ID = "selection";
+
+ private static final class MatchingTreeNodePredicate implements
Predicate<UIComponent> {
+
+ private String type;
+
+ public MatchingTreeNodePredicate(String type) {
+ super();
+ this.type = type;
+ }
+
+ public boolean apply(UIComponent input) {
+ if (!(input instanceof AbstractTreeNode)) {
+ return false;
+ }
+
+ if (!input.isRendered()) {
+ return false;
+ }
+
+ String nodeType = ((AbstractTreeNode) input).getType();
+ if (type == null && nodeType == null) {
+ return true;
+ }
+
+ return type != null && type.equals(nodeType);
+ }
+ };
+
+ private static final Converter ROW_KEY_CONVERTER = new SequenceRowKeyConverter();
+
+ /**
+ * @author Nick Belaevski
+ *
+ */
+ private final class TreeComponentState implements DataComponentState {
+ public Range getRange() {
+ return new TreeRange(getFacesContext(), AbstractTree.this);
+ }
+ }
+
+ private enum PropertyKeys {
+ expanded, selection
+ }
+
+ private transient TreeDecoderHelper treeDecoderHelper = new TreeDecoderHelper(this);
+
+ public AbstractTree() {
+ setRendererType("org.richfaces.TreeRenderer");
+ }
+
+ public abstract Object getValue();
+
+ public abstract boolean isImmediate();
+
+ @Override
+ public String getFamily() {
+ return COMPONENT_FAMILY;
+ }
+
+ @Attribute(defaultValue = "SwitchType.DEFAULT")
+ public abstract SwitchType getToggleType();
+
+ @Attribute(defaultValue = "SwitchType.client")
+ public abstract SwitchType getSelectionType();
+
+ public abstract String getNodeType();
+
+ public Collection<Object> getSelection() {
+ @SuppressWarnings("unchecked")
+ Collection<Object> selection = (Collection<Object>)
getStateHelper().eval(PropertyKeys.selection);
+ if (selection == null) {
+ selection = new HashSet<Object>();
+
+ ValueExpression ve = getValueExpression(PropertyKeys.selection.toString());
+ if (ve != null) {
+ ve.setValue(getFacesContext().getELContext(), selection);
+ } else {
+ getStateHelper().put(PropertyKeys.selection, selection);
+ }
+ }
+
+ return selection;
+ }
+
+ public void setSelection(Collection<Object> selection) {
+ getStateHelper().put(PropertyKeys.selection, selection);
+ }
+
+ @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() {
+ if (getRowKey() == null) {
+ return true;
+ }
+
+ 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()
+ */
+ @Override
+ protected ExtendedDataModel<?> createExtendedDataModel() {
+ TreeDataModelImpl model = new TreeDataModelImpl();
+ model.setWrappedData(getValue());
+ return model;
+ }
+
+ @Override
+ protected DataComponentState createComponentState() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Converter getRowKeyConverter() {
+ Converter converter = super.getRowKeyConverter();
+ if (converter == null) {
+ converter = ROW_KEY_CONVERTER;
+ }
+ return converter;
+ }
+
+ 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(),
+ new MatchingTreeNodePredicate(getNodeType()));
+
+ 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);
+ }
+ } else if (event instanceof TreeSelectionEvent) {
+ TreeSelectionEvent selectionEvent = (TreeSelectionEvent) event;
+
+ Collection<Object> selection = getSelection();
+
+ for (Object addedKey: selectionEvent.getAddedKeys()) {
+ selection.add(addedKey);
+ }
+
+ for (Object removedKey: selectionEvent.getRemovedKeys()) {
+ selection.remove(removedKey);
+ }
+ }
+ }
+
+ @Override
+ protected VisitResult visitDataChildrenMetaComponents(ExtendedVisitContext
extendedVisitContext,
+ VisitCallback callback) {
+
+ if (ExtendedVisitContextMode.RENDER == extendedVisitContext.getVisitMode()) {
+ VisitResult result =
extendedVisitContext.invokeMetaComponentVisitCallback(this, callback,
NODE_META_COMPONENT_ID);
+ if (result != VisitResult.ACCEPT) {
+ return result;
+ }
+ }
+
+ return super.visitDataChildrenMetaComponents(extendedVisitContext, callback);
+ }
+
+ @Override
+ protected boolean visitFixedChildren(VisitContext visitContext, VisitCallback
callback) {
+ if (visitContext instanceof ExtendedVisitContext) {
+ ExtendedVisitContext extendedVisitContext = (ExtendedVisitContext)
visitContext;
+
+ if (ExtendedVisitContextMode.RENDER == extendedVisitContext.getVisitMode())
{
+ VisitResult result =
extendedVisitContext.invokeMetaComponentVisitCallback(this, callback,
SELECTION_META_COMPONENT_ID);
+ if (result != VisitResult.ACCEPT) {
+ return result == VisitResult.COMPLETE;
+ }
+ }
+ }
+
+ return super.visitFixedChildren(visitContext, callback);
+ }
+
+ void decodeMetaComponent(FacesContext context, String metaComponentId) {
+ ((MetaComponentRenderer) getRenderer(context)).decodeMetaComponent(context, this,
metaComponentId);
+ }
+
+ public void encodeMetaComponent(FacesContext context, String metaComponentId) throws
IOException {
+ ((MetaComponentRenderer) getRenderer(context)).encodeMetaComponent(context, this,
metaComponentId);
+ }
+
+ public String resolveClientId(FacesContext facesContext, UIComponent
contextComponent, String metaComponentId) {
+ if (NODE_META_COMPONENT_ID.equals(metaComponentId) ||
SELECTION_META_COMPONENT_ID.equals(metaComponentId)) {
+ return getClientId(facesContext) +
MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR + metaComponentId;
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Iterator<UIComponent> dataChildren() {
+ AbstractTreeNode treeNodeComponent = getTreeNodeComponent();
+ if (treeNodeComponent != null) {
+ return
Iterators.<UIComponent>concat(Iterators.<UIComponent>singletonIterator(treeNodeComponent),
+ Iterators.singletonIterator(treeDecoderHelper));
+ } else {
+ return Iterators.<UIComponent>singletonIterator(treeDecoderHelper);
+ }
+ }
+
+ @Override
+ public DataComponentState getComponentState() {
+ return new TreeComponentState();
+ }
+
+ public void addToggleListener(TreeToggleListener listener) {
+ addFacesListener(listener);
+ }
+
+ public TreeToggleListener[] getTreeToggleListeners() {
+ return (TreeToggleListener[]) getFacesListeners(TreeToggleListener.class);
+ }
+
+ public void removeToggleListener(TreeToggleListener listener) {
+ removeFacesListener(listener);
+ }
+
+ public void addSelectionListener(TreeSelectionListener listener) {
+ addFacesListener(listener);
+ }
+
+ public TreeSelectionListener[] getSelectionListeners() {
+ return (TreeSelectionListener[]) getFacesListeners(TreeSelectionListener.class);
+ }
+
+ public void removeSelectionListener(TreeSelectionListener listener) {
+ removeFacesListener(listener);
+ }
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java
(from rev 19837,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTreeNode.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,96 @@
+/*
+ * 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;
+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
+ *
+ */
+@JsfComponent(
+ type = AbstractTreeNode.COMPONENT_TYPE,
+ family = AbstractTreeNode.COMPONENT_FAMILY,
+ tag = @Tag(name = "treeNode"),
+ renderer = @JsfRenderer(type = "org.richfaces.TreeNodeRenderer")
+)
+public abstract class AbstractTreeNode extends UIComponentBase {
+
+ public static final String COMPONENT_TYPE = "org.richfaces.TreeNode";
+
+ public static final String COMPONENT_FAMILY = "org.richfaces.TreeNode";
+
+ public AbstractTreeNode() {
+ setRendererType("org.richfaces.TreeNodeRenderer");
+ }
+
+ @Override
+ public String getFamily() {
+ return COMPONENT_FAMILY;
+ }
+
+ @Attribute(defaultValue = "findTreeComponent().isImmediate()")
+ public abstract boolean isImmediate();
+
+ public abstract String getType();
+
+ 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();
+ }
+ }
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
(from rev 19798,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeDecoderHelper.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,66 @@
+/*
+ * 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;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public 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 UIComponent getParent() {
+ return tree;
+ }
+
+ @Override
+ public boolean isInView() {
+ return tree.isInView();
+ }
+
+ @Override
+ public String getFamily() {
+ return null;
+ }
+
+ @Override
+ public void decode(FacesContext context) {
+ super.decode(context);
+ tree.decodeMetaComponent(context, AbstractTree.NODE_META_COMPONENT_ID);
+ }
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java (from
rev 19832,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/component/TreeRange.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java
(rev 0)
+++ trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,57 @@
+/*
+ * 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.context.FacesContext;
+
+import org.ajax4jsf.model.Range;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TreeRange implements Range {
+
+ private FacesContext facesContext;
+
+ private AbstractTree tree;
+
+ private boolean traverseAll;
+
+ public TreeRange(FacesContext facesContext, AbstractTree tree) {
+ super();
+ this.facesContext = facesContext;
+ this.tree = tree;
+
+ traverseAll = (SwitchType.client == tree.getToggleType());
+ }
+
+ public boolean shouldIterateChildren(Object rowKey) {
+ if (traverseAll) {
+ return true;
+ }
+
+ tree.setRowKey(facesContext, rowKey);
+ return tree.isExpanded();
+ }
+
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/convert (from rev 19789,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/convert)
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java (from
rev 19789,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/SequenceRowKey.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java
(rev 0)
+++ trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,77 @@
+/*
+ * 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.model;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.common.collect.ObjectArrays;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class SequenceRowKey<T> implements Serializable {
+
+ private static final long serialVersionUID = 5605581090240141910L;
+
+ private T[] simpleKeys;
+
+ public SequenceRowKey(T... keys) {
+ super();
+ this.simpleKeys = keys;
+ }
+
+ public T[] getSimpleKeys() {
+ return simpleKeys;
+ }
+
+ public SequenceRowKey<T> append(T segment) {
+ return new SequenceRowKey<T>(ObjectArrays.concat(simpleKeys, segment));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(simpleKeys);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ SequenceRowKey<?> other = (SequenceRowKey<?>) obj;
+ if (!Arrays.equals(simpleKeys, other.simpleKeys)) {
+ return false;
+ }
+ return true;
+ }
+}
Copied:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKeyIterator.java (from
rev 19789,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/SequenceRowKeyIterator.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKeyIterator.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKeyIterator.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,71 @@
+/*
+ * 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.model;
+
+import java.util.Iterator;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class SequenceRowKeyIterator<T> implements Iterator<Object> {
+
+ private int counter = 0;
+
+ private SequenceRowKey<Integer> baseKey;
+
+ private Iterator<T> itr;
+
+ private T element;
+
+ private SequenceRowKey<Integer> elementKey;
+
+ public SequenceRowKeyIterator(SequenceRowKey<Integer> baseKey,
Iterator<T> itr) {
+ super();
+ this.baseKey = baseKey;
+ this.itr = itr;
+ }
+
+ public boolean hasNext() {
+ return itr.hasNext();
+ }
+
+ public Object next() {
+ element = itr.next();
+ elementKey = baseKey.append(counter++);
+
+ return elementKey;
+ }
+
+ public T getElement() {
+ return element;
+ }
+
+ public SequenceRowKey<Integer> getElementKey() {
+ return elementKey;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java
(from rev 19801,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeDataModelImpl.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,184 @@
+/*
+ * 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.model;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.faces.context.FacesContext;
+import javax.swing.tree.TreeNode;
+
+import org.ajax4jsf.model.DataVisitResult;
+import org.ajax4jsf.model.DataVisitor;
+import org.ajax4jsf.model.ExtendedDataModel;
+import org.ajax4jsf.model.Range;
+import org.richfaces.component.TreeRange;
+
+import com.google.common.collect.Iterators;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TreeDataModelImpl extends ExtendedDataModel<TreeNode> {
+
+ private static final SequenceRowKey<Integer> EMPTY_SEQUENCE_ROW_KEY = new
SequenceRowKey<Integer>();
+
+ private SwingTreeNodeImpl<?> rootNode;
+
+ private TreeNode selectedNode;
+
+ private SequenceRowKey<Integer> selectedRowKey;
+
+ private Iterator<TreeNode> findChildren(SequenceRowKey<Integer>
compositeKey) {
+ TreeNode treeNode = findNode(compositeKey);
+
+ if (treeNode == null) {
+ return Iterators.emptyIterator();
+ }
+
+ return Iterators.forEnumeration((Enumeration<TreeNode>)
treeNode.children());
+ }
+
+ private TreeNode findNode(SequenceRowKey<Integer> compositeKey) {
+ if (compositeKey == null) {
+ return null;
+ }
+
+ TreeNode result = rootNode;
+
+ for (Integer simpleKey : compositeKey.getSimpleKeys()) {
+ int idx = simpleKey.intValue();
+
+ if (idx < result.getChildCount()) {
+ result = result.getChildAt(idx);
+ } else {
+ result = null;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void setRowKey(Object key) {
+ this.selectedRowKey = (SequenceRowKey<Integer>) key;
+ this.selectedNode = findNode(selectedRowKey);
+ }
+
+ @Override
+ public Object getRowKey() {
+ return selectedRowKey;
+ }
+
+ @Override
+ public boolean isRowAvailable() {
+ return selectedNode != null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.faces.model.DataModel#getRowCount()
+ */
+ @Override
+ public int getRowCount() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public TreeNode getRowData() {
+ return selectedNode;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.faces.model.DataModel#getRowIndex()
+ */
+ @Override
+ public int getRowIndex() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.faces.model.DataModel#setRowIndex(int)
+ */
+ @Override
+ public void setRowIndex(int rowIndex) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Object getWrappedData() {
+ return rootNode.getChildrenList();
+ }
+
+ @Override
+ public void setWrappedData(Object data) {
+ this.rootNode = new SwingTreeNodeImpl((List<TreeNode>) data);
+ }
+
+ private SequenceRowKey<Integer> castKeyAndWrapNull(Object rowKey) {
+ if (rowKey == null) {
+ return EMPTY_SEQUENCE_ROW_KEY;
+ }
+
+ return (SequenceRowKey<Integer>) rowKey;
+ }
+
+ public Iterator<Object> getChildrenIterator(FacesContext faces, Object rowKey)
{
+ SequenceRowKey<Integer> sequenceKey = castKeyAndWrapNull(rowKey);
+ Iterator<TreeNode> itr = findChildren(sequenceKey);
+
+ 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();
+
+ DataVisitResult visitResult = visitor.process(context, object, argument);
+ if (visitResult == DataVisitResult.CONTINUE) {
+ if (((TreeRange) range).shouldIterateChildren(object)) {
+ 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
+
+ if (((TreeRange) range).shouldIterateChildren(null)) {
+ Iterator<Object> iterator = getChildrenIterator(context, null);
+ walk(context, visitor, range, argument, iterator);
+ }
+ }
+
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java
(from rev 19801,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,138 @@
+/*
+ * 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.renderkit;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.richfaces.component.AbstractTree;
+import org.richfaces.component.TreeRange;
+import org.richfaces.component.util.HtmlUtil;
+import org.richfaces.renderkit.TreeRendererBase.NodeState;
+import org.richfaces.renderkit.TreeRendererBase.QueuedData;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.UnmodifiableIterator;
+
+abstract class TreeEncoderBase {
+
+ private static final String TREE_NODE_HANDLE_CLASS_ATTRIBUTE =
"__treeNodeHandleClass";
+
+ private static final String TREE_NODE_ICON_CLASS_ATTRIBUTE =
"__treeNodeIconClass";
+
+ protected final FacesContext context;
+
+ protected final ResponseWriter responseWriter;
+
+ protected final AbstractTree tree;
+
+ private TreeRange treeRange;
+
+ private LinkedList<QueuedData> queuedData = new
LinkedList<QueuedData>();
+
+ public TreeEncoderBase(FacesContext context, AbstractTree tree) {
+ super();
+ this.context = context;
+ this.responseWriter = context.getResponseWriter();
+ this.tree = tree;
+
+ this.treeRange = (TreeRange) tree.getComponentState().getRange();
+ }
+
+ protected void encodeTree(Iterator<Object> childrenIterator) throws IOException
{
+ Predicate<Object> renderedTreeNodeKeyPredicate = new
Predicate<Object>() {
+ public boolean apply(Object input) {
+ tree.setRowKey(input);
+
+ if (!tree.isRowAvailable()) {
+ return false;
+ }
+
+ return tree.getTreeNodeComponent() != null;
+ }
+ };
+
+ UnmodifiableIterator<Object> filteredIterator =
Iterators.filter(childrenIterator, renderedTreeNodeKeyPredicate);
+ while (filteredIterator.hasNext()) {
+ Object rowKey = filteredIterator.next();
+
+ encodeTreeNode(rowKey, !filteredIterator.hasNext());
+ }
+ }
+
+ protected void encodeTreeNode(Object rowKey, boolean isLastNode) throws IOException
{
+ if (!queuedData.isEmpty()) {
+ QueuedData data = queuedData.getLast();
+ if (!data.isEncoded()) {
+ tree.setRowKey(context, data.getRowKey());
+
+ writeTreeNodeStartElement(data.isExpanded() ? NodeState.expanded :
NodeState.collapsed, data.isLastNode());
+
+ data.setEncoded(true);
+ }
+ }
+
+ tree.setRowKey(context, rowKey);
+
+ boolean expanded = tree.isExpanded();
+ queuedData.add(new QueuedData(rowKey, isLastNode, expanded));
+
+ boolean iterateChildren = treeRange.shouldIterateChildren(rowKey);
+
+ if (iterateChildren) {
+ encodeTree(tree.getChildrenIterator(context, rowKey));
+ }
+
+ QueuedData data = queuedData.removeLast();
+ if (!data.isEncoded()) {
+ NodeState nodeState = iterateChildren ? NodeState.leaf :
NodeState.collapsed;
+ writeTreeNodeStartElement(nodeState, data.isLastNode());
+ }
+
+ writeTreeNodeEndElement();
+ }
+
+ protected void writeTreeNodeStartElement(NodeState nodeState, boolean isLast) throws
IOException {
+ context.getAttributes().put(TREE_NODE_HANDLE_CLASS_ATTRIBUTE,
nodeState.getHandleClass());
+ context.getAttributes().put(TREE_NODE_ICON_CLASS_ATTRIBUTE,
nodeState.getIconClass());
+
+ responseWriter.startElement(HtmlConstants.DIV_ELEM, tree);
+ responseWriter.writeAttribute(HtmlConstants.CLASS_ATTRIBUTE,
+ HtmlUtil.concatClasses("rf-tr-nd", isLast ?
"rf-tr-nd-last" : null, nodeState.getNodeClass()),
+ null);
+ responseWriter.writeAttribute(HtmlConstants.ID_ATTRIBUTE,
tree.getClientId(context), null);
+
+ tree.getTreeNodeComponent().encodeAll(context);
+ }
+
+ protected void writeTreeNodeEndElement() throws IOException {
+ responseWriter.endElement(HtmlConstants.DIV_ELEM);
+ }
+
+ public abstract void encode() throws IOException;
+
+}
\ No newline at end of file
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderFull.java
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeEncoderFull.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderFull.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderFull.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,50 @@
+/*
+ * 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.renderkit;
+
+import javax.faces.context.FacesContext;
+
+import org.richfaces.component.AbstractTree;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+class TreeEncoderFull extends TreeEncoderBase {
+
+ public TreeEncoderFull(FacesContext context, AbstractTree tree) {
+ super(context, tree);
+ }
+
+ public void encode() throws java.io.IOException {
+ Object initialRowKey = tree.getRowKey();
+ try {
+ encodeTree(tree.getChildrenIterator(context, null));
+ } finally {
+ try {
+ tree.setRowKey(context, initialRowKey);
+ } catch (Exception e) {
+ TreeRendererBase.LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+}
Copied:
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderPartial.java (from
rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeEncoderPartial.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderPartial.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderPartial.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,75 @@
+/*
+ * 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.renderkit;
+
+import java.io.IOException;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.PartialResponseWriter;
+
+import org.ajax4jsf.javascript.JSFunction;
+import org.richfaces.component.AbstractTree;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+class TreeEncoderPartial extends TreeEncoderBase {
+
+ private Object rowKey;
+
+ public TreeEncoderPartial(FacesContext context, AbstractTree tree) {
+ super(context, tree);
+
+ this.rowKey = tree.getRowKey();
+
+ if (this.rowKey == null) {
+ throw new NullPointerException("rowKey");
+ }
+ }
+
+ @Override
+ public void encode() throws IOException {
+ PartialResponseWriter prw =
context.getPartialViewContext().getPartialResponseWriter();
+ prw.startUpdate(tree.getClientId(context));
+
+ Object initialRowKey = tree.getRowKey();
+ try {
+
+ encodeTreeNode(rowKey, true);
+
+ prw.endUpdate();
+
+ } finally {
+ try {
+ tree.setRowKey(context, initialRowKey);
+ } catch (Exception e) {
+ TreeRendererBase.LOGGER.error(e.getMessage(), e);
+ }
+ }
+
+ prw.startEval();
+ JSFunction function = new
JSFunction("RichFaces.ui.TreeNode.initNodeByAjax", tree.getClientId(context));
+ prw.write(function.toScript());
+ prw.endEval();
+ }
+}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java
(from rev 19837,
sandbox/trunk/ui/tree-actual/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeRendererBase.java 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,327 @@
+/*
+ * 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.renderkit;
+
+import static org.richfaces.component.AbstractTree.NODE_META_COMPONENT_ID;
+import static org.richfaces.component.AbstractTree.SELECTION_META_COMPONENT_ID;
+import static org.richfaces.renderkit.util.AjaxRendererUtils.AJAX_FUNCTION_NAME;
+import static org.richfaces.renderkit.util.AjaxRendererUtils.buildAjaxFunction;
+import static org.richfaces.renderkit.util.AjaxRendererUtils.buildEventOptions;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+import javax.faces.context.PartialResponseWriter;
+import javax.faces.context.PartialViewContext;
+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.MetaComponentResolver;
+import org.richfaces.component.SwitchType;
+import org.richfaces.component.TreeDecoderHelper;
+import org.richfaces.event.TreeSelectionEvent;
+import org.richfaces.event.TreeToggleEvent;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+
+import com.google.common.base.Strings;
+
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public abstract class TreeRendererBase extends RendererBase implements
MetaComponentRenderer {
+
+ static final Logger LOGGER = RichfacesLogger.RENDERKIT.getLogger();
+
+ private static final JSReference PARAMS_JS_REF = new
JSReference("params");
+
+ private static final JSReference SOURCE_JS_REF = new
JSReference("source");
+
+ private static final String NEW_NODE_TOGGLE_STATE =
"__NEW_NODE_TOGGLE_STATE";
+
+ private static final String SELECTION_STATE = "__SELECTION_STATE";
+
+ enum NodeState {
+ expanded("rf-tr-nd-exp", "rf-trn-hnd-exp",
"rf-trn-ico-nd"),
+ collapsed("rf-tr-nd-colps", "rf-trn-hnd-colps",
"rf-trn-ico-nd"),
+ leaf("rf-tr-nd-lf", "rf-trn-hnd-lf",
"rf-trn-ico-lf");
+
+ private String nodeClass;
+
+ private String handleClass;
+
+ private String iconClass;
+
+ private NodeState(String nodeClass, String handleClass, String iconClass) {
+ this.nodeClass = nodeClass;
+ this.handleClass = handleClass;
+ this.iconClass = iconClass;
+ }
+
+ public String getNodeClass() {
+ return nodeClass;
+ }
+
+ public String getHandleClass() {
+ return handleClass;
+ }
+
+ public String getIconClass() {
+ return iconClass;
+ }
+
+ }
+
+ static final class QueuedData {
+
+ private Object rowKey;
+
+ private boolean lastNode;
+
+ private boolean expanded;
+
+ private boolean encoded;
+
+ public QueuedData(Object rowKey, boolean lastNode, boolean expanded) {
+ this.rowKey = rowKey;
+ this.lastNode = lastNode;
+ this.expanded = expanded;
+ }
+
+ public void setEncoded(boolean encoded) {
+ this.encoded = encoded;
+ }
+
+ public boolean isEncoded() {
+ return encoded;
+ }
+
+ public Object getRowKey() {
+ return rowKey;
+ }
+
+ public boolean isLastNode() {
+ return lastNode;
+ }
+
+ public boolean isExpanded() {
+ return expanded;
+ }
+ }
+
+ public void encodeTree(FacesContext context, UIComponent component) throws
IOException {
+ AbstractTree tree = (AbstractTree) component;
+
+ new TreeEncoderFull(context, tree).encode();
+ }
+
+ protected String getDecoderHelperId(FacesContext facesContext) {
+ return UINamingContainer.getSeparatorChar(facesContext) +
TreeDecoderHelper.HELPER_ID;
+ }
+
+ protected String getAjaxSubmitFunction(FacesContext context, UIComponent component)
{
+ AbstractTree tree = (AbstractTree) component;
+
+ if (tree.getToggleType() != SwitchType.ajax && tree.getSelectionType() !=
SwitchType.ajax) {
+ return null;
+ }
+
+ JSFunction ajaxFunction = buildAjaxFunction(context, component,
AJAX_FUNCTION_NAME);
+ AjaxEventOptions eventOptions = buildEventOptions(context, component);
+
+ eventOptions.setAjaxComponent(SOURCE_JS_REF);
+ eventOptions.setClientParameters(PARAMS_JS_REF);
+
+ if (!eventOptions.isEmpty()) {
+ ajaxFunction.addParameter(eventOptions);
+ }
+ return ajaxFunction.toScript();
+ }
+
+ protected void encodeSelectionStateInput(FacesContext context, UIComponent component)
throws IOException {
+ ResponseWriter writer = context.getResponseWriter();
+ writer.startElement(HtmlConstants.INPUT_ELEM, component);
+ writer.writeAttribute(HtmlConstants.TYPE_ATTR, "hidden", null);
+ String selectionStateInputId = getSelectionStateInputId(context, component);
+ writer.writeAttribute(HtmlConstants.NAME_ATTRIBUTE, selectionStateInputId,
null);
+ writer.writeAttribute(HtmlConstants.ID_ATTRIBUTE, selectionStateInputId, null);
+ writer.writeAttribute(HtmlConstants.CLASS_ATTRIBUTE, "rf-tr-sel-inp",
null);
+
+ String selectedNodeId = "";
+ AbstractTree tree = (AbstractTree) component;
+
+ Iterator<Object> selectedKeys = tree.getSelection().iterator();
+
+ if (selectedKeys.hasNext()) {
+ Object selectionKey = selectedKeys.next();
+ Object initialKey = tree.getRowKey();
+ try {
+ tree.setRowKey(context, selectionKey);
+ if (tree.isRowAvailable()) {
+ selectedNodeId = tree.getClientId(context);
+ }
+ } finally {
+ try {
+ tree.setRowKey(context, initialKey);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ if (selectedKeys.hasNext()) {
+ //TODO - better message
+ throw new IllegalArgumentException("Selection object should not contain
more than selected keys!");
+ }
+
+ writer.writeAttribute(HtmlConstants.VALUE_ATTRIBUTE, selectedNodeId, null);
+
+ writer.endElement(HtmlConstants.INPUT_ELEM);
+ }
+
+ protected String getSelectionStateInputId(FacesContext context, UIComponent
component) {
+ return component.getClientId(context) + SELECTION_STATE;
+ }
+
+ protected SwitchType getSelectionMode(FacesContext context, UIComponent component) {
+ AbstractTree tree = (AbstractTree) component;
+
+ SwitchType selectionType = tree.getSelectionType();
+ if (selectionType != null && selectionType != SwitchType.ajax &&
selectionType != SwitchType.client) {
+ //TODO - better message
+ throw new IllegalArgumentException(String.valueOf(selectionType));
+ }
+
+ return selectionType;
+ }
+
+ protected String getNamingContainerSeparatorChar(FacesContext context) {
+ return String.valueOf(UINamingContainer.getSeparatorChar(context));
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.renderkit.MetaComponentRenderer#encodeMetaComponent(javax.faces.context.FacesContext,
javax.faces.component.UIComponent, java.lang.String)
+ */
+ public void encodeMetaComponent(FacesContext context, UIComponent component, String
metaComponentId)
+ throws IOException {
+
+ if (NODE_META_COMPONENT_ID.equals(metaComponentId)) {
+ AbstractTree tree = (AbstractTree) component;
+ new TreeEncoderPartial(context, tree).encode();
+ } else if (SELECTION_META_COMPONENT_ID.equals(metaComponentId)) {
+ PartialResponseWriter writer =
context.getPartialViewContext().getPartialResponseWriter();
+
+ writer.startUpdate(getSelectionStateInputId(context, component));
+ encodeSelectionStateInput(context, component);
+ writer.endUpdate();
+
+ writer.startEval();
+
+ JSFunction function = new JSFunction("RichFaces.$",
component.getClientId(context));
+ writer.write(function.toScript() + ".__updateSelection();");
+
+ writer.endEval();
+ } else {
+ throw new IllegalArgumentException(metaComponentId);
+ }
+
+ // TODO Auto-generated method stub
+
+ }
+
+ public void decodeMetaComponent(FacesContext context, UIComponent component, String
metaComponentId) {
+ if (NODE_META_COMPONENT_ID.equals(metaComponentId)) {
+ final Map<String, String> map =
context.getExternalContext().getRequestParameterMap();
+ String newToggleState = map.get(component.getClientId(context) +
NEW_NODE_TOGGLE_STATE);
+ if (newToggleState != null) {
+
+ AbstractTree tree = (AbstractTree) component;
+ AbstractTreeNode treeNode = tree.getTreeNodeComponent();
+
+ if (treeNode == null) {
+ return;
+ }
+
+ boolean expanded = Boolean.valueOf(newToggleState);
+ if (tree.isExpanded() ^ expanded) {
+ new TreeToggleEvent(treeNode, expanded).queue();
+ }
+
+ PartialViewContext pvc = context.getPartialViewContext();
+ if (pvc.isAjaxRequest()) {
+ pvc.getRenderIds().add(tree.getClientId(context) +
MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR
+ + AbstractTree.NODE_META_COMPONENT_ID);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void decode(FacesContext context, UIComponent component) {
+ super.decode(context, component);
+
+ Map<String, String> map =
context.getExternalContext().getRequestParameterMap();
+ String selectedNode = map.get(getSelectionStateInputId(context, component));
+ AbstractTree tree = (AbstractTree) component;
+
+ Object selectionRowKey = null;
+
+ if (!Strings.isNullOrEmpty(selectedNode)) {
+ String selectionRowKeyString =
selectedNode.substring(component.getClientId(context).length() + 1 /* naming container
separator char */);
+ selectionRowKey = tree.getRowKeyConverter().getAsObject(context, component,
selectionRowKeyString);
+ }
+
+ Collection<Object> selection = tree.getSelection();
+
+ Set<Object> addedKeys = new HashSet<Object>(2);
+ Set<Object> removedKeys = new HashSet<Object>(2);
+
+ if (selectionRowKey == null) {
+ removedKeys.addAll(selection);
+ } else if (!selection.contains(selectionRowKey)) {
+ addedKeys.add(selectionRowKey);
+ removedKeys.addAll(selection);
+ }
+
+ if (!removedKeys.isEmpty() || !addedKeys.isEmpty()) {
+ new TreeSelectionEvent(component, addedKeys, removedKeys).queue();
+ }
+
+ PartialViewContext pvc = context.getPartialViewContext();
+ if (pvc.isAjaxRequest()) {
+ pvc.getRenderIds().add(tree.getClientId(context) +
MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR
+ + AbstractTree.SELECTION_META_COMPONENT_ID);
+ }
+ }
+}
Copied: trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/last.gif
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/last.gif)
===================================================================
(Binary files differ)
Copied:
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/leaf_icon.gif
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/leaf_icon.gif)
===================================================================
(Binary files differ)
Copied: trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/line.gif
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/line.gif)
===================================================================
(Binary files differ)
Copied:
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/minus.gif (from
rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/minus.gif)
===================================================================
(Binary files differ)
Copied:
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/node_icon.gif
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/node_icon.gif)
===================================================================
(Binary files differ)
Copied: trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/plus.gif
(from rev 19794,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/plus.gif)
===================================================================
(Binary files differ)
Copied:
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.ecss (from
rev 19834,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.ecss)
===================================================================
--- trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.ecss
(rev 0)
+++
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.ecss 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,71 @@
+.rf-trn {
+ background: "url(#{resource['org.richfaces.images:last.gif']}) no-repeat
center left";
+ cursor: default;
+ font-size: '#{richSkin.generalSizeFont}';
+ font-family: '#{richSkin.generalFamilyFont}';
+ color: '#{richSkin.generalTextColor}';
+ padding: 1px 0px 1px 0px;
+ overflow: hidden;
+ width: 100%;
+ white-space: nowrap;
+}
+
+.rf-trn-lbl {
+ padding: 0px 4px 0px 2px;
+ vertical-align: middle;
+ cursor: pointer;
+ display: inline-block;
+}
+
+.rf-trn-cnt {
+ display: inline-block;
+}
+
+.rf-trn-sel {
+ background: '#{richSkin.additionalBackgroundColor}';
+}
+
+.rf-tr-nd {
+ background: "url(#{resource['org.richfaces.images:line.gif']})
repeat-y";
+}
+
+.rf-tr-nd-last {
+ background: none;
+}
+
+.rf-tr-nd .rf-tr-nd {
+ margin-left: 16px;
+}
+
+.rf-trn-ico, .rf-trn-hnd {
+ vertical-align: middle;
+ margin: 0px;
+ cursor: pointer;
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+}
+
+.rf-trn-hnd-lf {
+ cursor: default;
+}
+
+.rf-trn-hnd-colps {
+ background: "url(#{resource['org.richfaces.images:plus.gif']}) no-repeat
center";
+}
+
+.rf-trn-hnd-exp {
+ background: "url(#{resource['org.richfaces.images:minus.gif']}) no-repeat
center";
+}
+
+.rf-trn-ico-nd {
+ background: "url(#{resource['org.richfaces.images:node_icon.gif']})
no-repeat center";
+}
+
+.rf-trn-ico-lf {
+ background: "url(#{resource['org.richfaces.images:leaf_icon.gif']})
no-repeat center";
+}
+
+.rf-tr-nd.rf-tr-nd-colps .rf-tr-nd {
+ display: none;
+}
Copied: trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
(from rev 19834,
sandbox/trunk/ui/tree-actual/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js)
===================================================================
--- trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
(rev 0)
+++
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js 2010-11-01
15:43:05 UTC (rev 19848)
@@ -0,0 +1,385 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, 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.
+ */
+(function($, richfaces) {
+
+ var DECODER_HELPER_ID = "__treeDecoderHelper";
+
+ var NEW_NODE_TOGGLE_STATE = "__NEW_NODE_TOGGLE_STATE";
+
+ var SELECTION_STATE = "__SELECTION_STATE";
+
+ var TREE_CLASSES = ["rf-tr-nd-colps", "rf-tr-nd-exp"];
+
+ var TREE_HANDLE_CLASSES = ["rf-trn-hnd-colps", "rf-trn-hnd-exp"];
+
+ richfaces.ui = richfaces.ui || {};
+
+ richfaces.ui.TreeNode = richfaces.BaseComponent.extendClass({
+
+ name: "TreeNode",
+
+ init: function (id) {
+ this.id = id;
+ this.elt = $(this.attachToDom());
+
+ this.__children = new Array();
+
+ this.__initializeChildren();
+ },
+
+ destroy: function() {
+ if (this.isSelected()) {
+ this.getTree().__resetSelection();
+ }
+
+ if (this.parent) {
+ this.parent.removeChild(this);
+ this.parent = null;
+ }
+
+ this.__clientToggleStateInput = null;
+
+ this.__clearChildren();
+
+ this.elt = null;
+ },
+
+ __initializeChildren: function() {
+ var _this = this;
+ this.elt.children(".rf-tr-nd").each(function() {
+ _this.addChild(new richfaces.ui.TreeNode(this));
+ });
+ },
+
+ __getHandle: function() {
+ return this.elt.find(" > .rf-trn:first > .rf-trn-hnd:first");
+ },
+
+ __getContent: function() {
+ return this.elt.find(" > .rf-trn:first > .rf-trn-cnt:first");
+ },
+
+ getParent: function() {
+ return this.__parent;
+ },
+
+ setParent: function(newParent) {
+ this.__parent = newParent;
+ },
+
+ addChild: function(child, idx) {
+ var start;
+ if (typeof idx != 'undefined') {
+ start = idx;
+ } else {
+ start = this.__children.length;
+ }
+
+ this.__children.splice(start, 0, child);
+ child.setParent(this);
+ },
+
+ removeChild: function(child) {
+ if (this.__children.length) {
+ var idx = this.__children.indexOf(child);
+ if (idx != -1) {
+ var removedChildren = this.__children.splice(idx, 1);
+ if (removedChildren) {
+ for (var i = 0; i < removedChildren.length; i++) {
+ removedChildren[i].setParent(undefined);
+ }
+ }
+ }
+ }
+ },
+
+ __clearChildren: function() {
+ for (var i = 0; i < this.__children.length; i++) {
+ this.__children[i].setParent(undefined);
+ }
+
+ this.__children = new Array();
+ },
+
+ isExpanded: function() {
+ return !this.isLeaf() &&
this.__getHandle().hasClass("rf-trn-hnd-exp");
+ },
+
+ isCollapsed: function() {
+ return !this.isLeaf() &&
this.__getHandle().hasClass("rf-trn-hnd-colps");
+ },
+
+ isLeaf: function() {
+ return this.__getHandle().hasClass("rf-trn-hnd-lf");
+ },
+
+ toggle: function() {
+ if (this.isLeaf()) {
+ return;
+ }
+
+ if (this.isCollapsed()) {
+ this.expand();
+ } else {
+ this.collapse();
+ }
+ },
+
+ __updateClientToggleStateInput: function(newState) {
+ if (!this.__clientToggleStateInput) {
+ this.__clientToggleStateInput = $("<input type='hidden'
/>").appendTo(this.elt)
+ .attr({name: this.elt.attr("id") + NEW_NODE_TOGGLE_STATE});
+ }
+
+ this.__clientToggleStateInput.val(newState.toString());
+
+ },
+
+ __changeToggleState: function(newState) {
+ if (!this.isLeaf()) {
+ if (newState ^ this.isExpanded()) {
+ var tree = this.getTree();
+
+ switch (tree.getToggleType()) {
+ case 'client':
+ this.elt.addClass(TREE_CLASSES[newState ? 1 :
0]).removeClass(TREE_CLASSES[!newState ? 1 : 0]);
+ this.__getHandle().addClass(TREE_HANDLE_CLASSES[newState ? 1 :
0]).removeClass(TREE_HANDLE_CLASSES[!newState ? 1 : 0]);
+ this.__updateClientToggleStateInput(newState);
+ break;
+
+ case 'ajax':
+ case 'server':
+ //TODO - event?
+ tree.__sendToggleRequest(null, this.getId(), newState);
+ break;
+ }
+ }
+ }
+ },
+
+ collapse: function() {
+ this.__changeToggleState(false);
+ },
+
+ expand: function() {
+ this.__changeToggleState(true);
+ },
+
+ __setSelected: function(value) {
+ var content = this.__getContent();
+ if (value) {
+ content.addClass("rf-trn-sel");
+ } else {
+ content.removeClass("rf-trn-sel");
+ }
+
+ this.__selected = value;
+ },
+
+ isSelected: function() {
+ return this.__selected;
+ },
+
+ getTree: function() {
+ return this.getParent().getTree();
+ },
+
+ getId: function() {
+ return richfaces.getDomElement(this.id).id;
+ }
+
+ });
+
+ richfaces.ui.TreeNode.initNodeByAjax = function(nodeId) {
+ var node = $(document.getElementById(nodeId));
+
+ if (node.nextAll(".rf-tr-nd:first").length != 0) {
+ node.removeClass("rf-tr-nd-last");
+ }
+
+ var parent = node.parent(".rf-tr-nd, .rf-tr");
+
+ var idx = node.prevAll(".rf-tr-nd").length;
+
+ var parentNode = richfaces.$(parent[0]);
+ var newChild = new richfaces.ui.TreeNode(node[0]);
+ parentNode.addChild(newChild, idx);
+ parentNode.getTree().__updateSelection();
+ };
+
+ var findTree = function(elt) {
+ return richfaces.$($(elt).closest(".rf-tr"));
+ };
+
+ var findTreeNode = function(elt) {
+ return richfaces.$($(elt).closest(".rf-tr-nd"));
+ };
+
+ var isEventForAnotherTree = function(tree, elt) {
+ return tree != findTree(elt);
+ };
+
+ var ncSepChar;
+
+ richfaces.ui.Tree = richfaces.ui.TreeNode.extendClass({
+
+ name: "Tree",
+
+ init: function (id, options) {
+ this.$super.init.call(this, id);
+
+ this.__toggleType = options.toggleType || 'ajax';
+ this.__selectionType = options.selectionType || 'client';
+
+ if (options.ajaxSubmitFunction) {
+ this.__ajaxSubmitFunction = new Function("event", "source",
"params", options.ajaxSubmitFunction);
+ }
+
+ this.__selectionInput = $(" > .rf-tr-sel-inp", this.elt);
+
+ this.elt.delegate(".rf-trn-hnd", "click", this,
this.__itemHandleClicked);
+ this.elt.delegate(".rf-trn-cnt", "mousedown", this,
this.__itemContentClicked);
+
+ this.__updateSelection();
+ },
+
+ destroy: function() {
+ this.$super.destroy();
+
+ this.elt.undelegate(".rf-trn-hnd", "click",
this.__itemHandleClicked);
+ this.elt.undelegate(".rf-trn-cnt", "mousedown",
this.__itemContentClicked);
+
+ this.__itemContentClickedHandler = null;
+ this.__selectionInput = null;
+ this.__ajaxSubmitFunction = null;
+ },
+
+ __itemHandleClicked: function(event) {
+ var theTree = event.data;
+ if (isEventForAnotherTree(theTree, this)) {
+ return;
+ }
+
+ var treeNode = findTreeNode(this);
+ treeNode.toggle();
+ },
+
+ __itemContentClicked: function(event) {
+ var theTree = event.data;
+ if (isEventForAnotherTree(theTree, this)) {
+ return;
+ }
+
+ var treeNode = findTreeNode(this);
+
+ if (event.ctrlKey) {
+ theTree.__toggleSelection(treeNode);
+ } else {
+ theTree.__addToSelection(treeNode);
+ }
+ },
+
+ __sendToggleRequest: function(event, toggleSource, newNodeState) {
+ var clientParams = {};
+ clientParams[toggleSource + NEW_NODE_TOGGLE_STATE] = newNodeState;
+
+ if (this.getToggleType() == 'server') {
+ var form = $(richfaces.getDomElement(this.id)).closest('form');
+ richfaces.submitForm(form, clientParams);
+ } else {
+ this.__ajaxSubmitFunction(event, toggleSource + ncSepChar + DECODER_HELPER_ID,
clientParams);
+ }
+ },
+
+ getToggleType: function() {
+ return this.__toggleType;
+ },
+
+ getSelectionType: function() {
+ return this.__selectionType;
+ },
+
+ getTree: function() {
+ return this;
+ },
+
+ __bindFocusHandler: function(elt) {
+ elt.mousedown(this.__itemContentClickedHandler);
+ },
+
+ __isSelected: function(node) {
+ return this.__selectedNodeId == node.getId();
+ },
+
+ __handleSelectionChange: function() {
+ if (this.getSelectionType() == 'client') {
+ this.__updateSelection();
+ } else {
+ this.__ajaxSubmitFunction(null, this.id);
+ }
+ },
+
+ __toggleSelection: function(node) {
+ if (this.__isSelected(node)) {
+ this.__selectionInput.val("");
+ } else {
+ this.__selectionInput.val(node.getId());
+ }
+
+ this.__handleSelectionChange();
+ },
+
+ __addToSelection: function(node) {
+ this.__selectionInput.val(node.getId());
+
+ this.__handleSelectionChange();
+ },
+
+ __resetSelection: function() {
+ this.__selectedNodeId = null;
+ this.__selectionInput.val("");
+ },
+
+ __updateSelection: function() {
+ var oldSelection = this.__selectedNodeId;
+ if (oldSelection) {
+ var oldSelectionNode = richfaces.$(oldSelection);
+ if (oldSelectionNode) {
+ oldSelectionNode.__setSelected(false);
+ }
+ }
+
+ var nodeId = this.__selectionInput.val();
+
+ var newSelectionNode = richfaces.$(nodeId);
+ if (newSelectionNode) {
+ newSelectionNode.__setSelected(true);
+ }
+ this.__selectedNodeId = nodeId;
+ }
+ });
+
+ richfaces.ui.Tree.setNamingContainerSeparatorChar = function(s) {
+ ncSepChar = s.charAt(0);
+ };
+
+}(jQuery, RichFaces));
\ No newline at end of file
Modified:
trunk/ui/iteration/ui/src/main/resources/META-INF/richfaces/resource-mappings.properties
===================================================================
---
trunk/ui/iteration/ui/src/main/resources/META-INF/richfaces/resource-mappings.properties 2010-11-01
15:40:40 UTC (rev 19847)
+++
trunk/ui/iteration/ui/src/main/resources/META-INF/richfaces/resource-mappings.properties 2010-11-01
15:43:05 UTC (rev 19848)
@@ -5,4 +5,10 @@
org.richfaces.images\:dsDigGrad.png=org.richfaces.renderkit.html.BaseGradient\
{baseColorParam=additionalBackgroundColor, gradientColorParam=tableBackgroundColor}
org.richfaces.images\:colHdrGrad.png=org.richfaces.renderkit.html.BaseGradient\
- {baseColorParam=tableSubHeaderBackgroundColor,
gradientColorParam=tableHeaderBackgroundColor}
\ No newline at end of file
+ {baseColorParam=tableSubHeaderBackgroundColor,
gradientColorParam=tableHeaderBackgroundColor}
+org.richfaces.images\:last.gif=org.richfaces\:last.gif
+org.richfaces.images\:line.gif=org.richfaces\:line.gif
+org.richfaces.images\:plus.gif=org.richfaces\:plus.gif
+org.richfaces.images\:minus.gif=org.richfaces\:minus.gif
+org.richfaces.images\:node_icon.gif=org.richfaces\:node_icon.gif
+org.richfaces.images\:leaf_icon.gif=org.richfaces\:leaf_icon.gif
\ No newline at end of file
Copied: trunk/ui/iteration/ui/src/main/templates/tree.template.xml (from rev 19832,
sandbox/trunk/ui/tree-actual/ui/src/main/templates/tree.template.xml)
===================================================================
--- trunk/ui/iteration/ui/src/main/templates/tree.template.xml
(rev 0)
+++ trunk/ui/iteration/ui/src/main/templates/tree.template.xml 2010-11-01 15:43:05 UTC
(rev 19848)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<cdk:root
xmlns="http://jboss.org/schema/richfaces/cdk/xhtml-el"
xmlns:cdk="http://jboss.org/schema/richfaces/cdk/core"
+
xmlns:c="http://jboss.org/schema/richfaces/cdk/jstl/core"
xmlns:cc="http://jboss.org/schema/richfaces/cdk/jsf/composite"
+
xmlns:javaee="http://java.sun.com/xml/ns/javaee">
+
+ <cc:interface>
+ <cdk:class>org.richfaces.renderkit.html.TreeRenderer</cdk:class>
+
<cdk:superclass>org.richfaces.renderkit.TreeRendererBase</cdk:superclass>
+ <cdk:component-family>org.richfaces.Tree</cdk:component-family>
+ <cdk:renderer-type>org.richfaces.TreeRenderer</cdk:renderer-type>
+ <cdk:renders-children>true</cdk:renders-children>
+
+ <cdk:resource-dependency name="base-component.reslib"
library="org.richfaces" />
+ <cdk:resource-dependency name="tree.js"
library="org.richfaces" />
+ <cdk:resource-dependency name="tree.ecss"
library="org.richfaces" />
+
+ <cdk:import package="org.richfaces.component"
names="SwitchType" />
+ </cc:interface>
+
+ <cc:implementation>
+ <div id="#{clientId}" class="#{concatClasses('rf-tr',
component.attributes['styleClass'])}"
+ cdk:passThroughWithExclusions="">
+ <cdk:body>
+ <cdk:call expression="encodeTree(facesContext, component)"
/>
+ </cdk:body>
+
+ <cdk:call expression="encodeSelectionStateInput(facesContext,
component)" />
+
+ <script type="text/javascript">
+
RichFaces.ui.Tree.setNamingContainerSeparatorChar(#{toScriptArgs(getNamingContainerSeparatorChar(facesContext))});
+ <cdk:scriptObject name="options">
+ <cdk:scriptOption attributes="toggleType"
defaultValue="SwitchType.DEFAULT" />
+ <cdk:scriptOption name="selectionType"
value="#{getSelectionMode(facesContext, component)}"
defaultValue="SwitchType.client" />
+ <cdk:scriptOption name="ajaxSubmitFunction"
value="#{getAjaxSubmitFunction(facesContext, component)}" />
+ </cdk:scriptObject>
+
+ new RichFaces.ui.Tree(#{toScriptArgs(clientId, options)});
+ </script>
+ </div>
+ </cc:implementation>
+
+</cdk:root>
Copied: trunk/ui/iteration/ui/src/main/templates/treeNode.template.xml (from rev 19839,
sandbox/trunk/ui/tree-actual/ui/src/main/templates/treeNode.template.xml)
===================================================================
--- trunk/ui/iteration/ui/src/main/templates/treeNode.template.xml
(rev 0)
+++ trunk/ui/iteration/ui/src/main/templates/treeNode.template.xml 2010-11-01 15:43:05 UTC
(rev 19848)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<cdk:root
xmlns="http://jboss.org/schema/richfaces/cdk/xhtml-el"
+
xmlns:cdk="http://jboss.org/schema/richfaces/cdk/core"
xmlns:c="http://jboss.org/schema/richfaces/cdk/jstl/core"
+
xmlns:cc="http://jboss.org/schema/richfaces/cdk/jsf/composite"
+
xmlns:javaee="http://java.sun.com/xml/ns/javaee">
+
+ <cc:interface>
+ <cdk:class>org.richfaces.renderkit.html.TreeNodeRenderer
+ </cdk:class>
+ <cdk:superclass>javax.faces.render.Renderer</cdk:superclass>
+ <cdk:component-family>org.richfaces.TreeNode
+ </cdk:component-family>
+ <cdk:renderer-type>org.richfaces.TreeNodeRenderer
+ </cdk:renderer-type>
+ </cc:interface>
+
+ <cc:implementation>
+ <div class="rf-trn">
+ <span class="rf-trn-hnd
#{facesContext.attributes['__treeNodeHandleClass']}" />
+ <span class="rf-trn-cnt">
+ <span class="rf-trn-ico
#{facesContext.attributes['__treeNodeIconClass']}" />
+ <span class="rf-trn-lbl">
+ <cdk:body />
+ </span>
+ </span>
+ </div>
+ </cc:implementation>
+
+</cdk:root>