You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2012/05/24 13:01:11 UTC

svn commit: r1342193 - in /myfaces/tobago/trunk: tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/ tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ tobago-core/src/main/java/org/apache/myfaces/tobago/...

Author: lofwyr
Date: Thu May 24 11:01:10 2012
New Revision: 1342193

URL: http://svn.apache.org/viewvc?rev=1342193&view=rev
Log:
TOBAGO-1049: TreeTable
 - make TreeListbox runnable with the new tree implementation

Modified:
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java
    myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/03-tree/03-listbox/tree-listbox.xhtml
    myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SelectOneListboxRenderer.java
    myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeLabelRenderer.java
    myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxNodeRenderer.java
    myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxRenderer.java
    myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java Thu May 24 11:01:10 2012
@@ -31,6 +31,7 @@ import javax.faces.context.FacesContext;
 import javax.faces.model.DataModel;
 import javax.swing.tree.DefaultMutableTreeNode;
 import java.io.IOException;
+import java.util.List;
 
 public abstract class AbstractUIData extends javax.faces.component.UIData implements InvokeOnComponent {
 
@@ -176,9 +177,27 @@ public abstract class AbstractUIData ext
    * @return The TreePath of the current row index.
    */
   public TreePath getPath() {
-    final DataModel model = getDataModel();
-    if (model instanceof TreeDataModel) {
-      return ((TreeDataModel) model).getPath();
+    if (isTreeModel()) {
+      return ((TreeDataModel) getDataModel()).getPath();
+    } else {
+      throw new IllegalStateException("Not a tree model");
+    }
+  }
+
+  /**
+   * @return Is the current row index representing a folder.
+   */
+  public boolean isFolder() {
+    if (isTreeModel()) {
+      return ((TreeDataModel) getDataModel()).isFolder();
+    } else {
+      throw new IllegalStateException("Not a tree model");
+    }
+  }
+
+  public List<Integer> getChildrensRowIndices() {
+    if (isTreeModel()) {
+      return dataModel.getChildrensRowIndices();
     } else {
       throw new IllegalStateException("Not a tree model");
     }

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java Thu May 24 11:01:10 2012
@@ -27,6 +27,8 @@ import org.apache.myfaces.tobago.compone
 import org.apache.myfaces.tobago.internal.taglib.declaration.HasCurrentMarkup;
 import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
 import org.apache.myfaces.tobago.internal.taglib.declaration.HasMarkup;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasVar;
 import org.apache.myfaces.tobago.internal.taglib.declaration.IsGridLayoutComponent;
 import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
 
@@ -44,7 +46,8 @@ import org.apache.myfaces.tobago.interna
         "org.apache.myfaces.tobago.TreeData"
     })
 public interface TreeListboxTagDeclaration
-    extends HasIdBindingAndRendered, IsRequired, IsGridLayoutComponent, HasMarkup, HasCurrentMarkup {
+    extends HasIdBindingAndRendered, HasValue, HasVar, IsGridLayoutComponent, HasMarkup, HasCurrentMarkup,
+    IsRequired {
 
   /**
    * Flag indicating whether or not this component should be render selectable items.

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java Thu May 24 11:01:10 2012
@@ -22,7 +22,9 @@ import org.slf4j.LoggerFactory;
 
 import javax.faces.model.DataModel;
 import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class TreeDataModel extends DataModel {
@@ -125,6 +127,10 @@ public class TreeDataModel extends DataM
     return new TreePath(getRowData());
   }
 
+  public boolean isFolder() {
+    return !getRowData().isLeaf();
+  }
+
   @Override
   public Object getWrappedData() {
     return data;
@@ -196,6 +202,18 @@ public class TreeDataModel extends DataM
     }
   }
 
+  public List<Integer> getChildrensRowIndices() {
+    final DefaultMutableTreeNode node = getRowData();
+    final int n = node.getChildCount();
+    final List<Integer> children = new ArrayList<Integer>(n);
+    for (int i = 0; i < n; i++) {
+      final Integer integer = back.get((DefaultMutableTreeNode) node.getChildAt(i));
+      if (integer != null) { // integer == null happens, when the node is not expanded XXX is this a good way to handle that case?
+        children.add(integer);
+      }
+    }
+    return children;
+  }
 
   /**
    * Here we cache some state information of the nodes, because we can't access the UITreeNode state of the other nodes

Modified: myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/03-tree/03-listbox/tree-listbox.xhtml
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/03-tree/03-listbox/tree-listbox.xhtml?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/03-tree/03-listbox/tree-listbox.xhtml (original)
+++ myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/03-tree/03-listbox/tree-listbox.xhtml Thu May 24 11:01:10 2012
@@ -27,7 +27,7 @@
 
   <tc:panel>
     <f:facet name="layout">
-      <tc:gridLayout rows="9*;16*"/>
+      <tc:gridLayout rows="50px;*;auto"/>
     </f:facet>
 
     <tc:out escape="false" value="(UNDER CONSTRUCTION) Tree Listbox"/>
@@ -38,5 +38,14 @@
       </tc:treeNode>
     </tc:treeListbox>
 
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto" rows="auto"/>
+      </f:facet>
+
+      <tc:panel/>
+      <tc:button label="Submit"/>
+    </tc:panel>
+
   </tc:panel>
 </ui:composition>

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SelectOneListboxRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SelectOneListboxRenderer.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SelectOneListboxRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SelectOneListboxRenderer.java Thu May 24 11:01:10 2012
@@ -71,7 +71,7 @@ public class SelectOneListboxRenderer ex
     writer.writeStyleAttribute(style);
     writer.writeClassAttribute(Classes.create(select));
     HtmlRendererUtils.renderTip(select, writer);
-    writer.writeAttribute(HtmlAttributes.SIZE, 2); // should be greater 1
+    writer.writeAttribute(HtmlAttributes.SIZE, 9); // must be > 1, but the real size comes from the layout
     if (!ComponentUtils.getBooleanAttribute(select, Attributes.REQUIRED)) {
       writer.writeAttribute(HtmlAttributes.ONCHANGE, "Tobago.selectOneListboxChange(this)", false);
       writer.writeAttribute(HtmlAttributes.ONCLICK, "Tobago.selectOneListboxClick(this)", false);

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeLabelRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeLabelRenderer.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeLabelRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeLabelRenderer.java Thu May 24 11:01:10 2012
@@ -17,12 +17,17 @@ package org.apache.myfaces.tobago.render
  * limitations under the License.
  */
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.myfaces.tobago.component.UITreeLabel;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
 import org.apache.myfaces.tobago.renderkit.LayoutComponentRendererBase;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,22 +42,31 @@ public class TreeLabelRenderer extends L
 
   public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
 
+    final AbstractUIData data = ComponentUtils.findAncestor(component, AbstractUIData.class);
+    final boolean listbox = data instanceof AbstractUITreeListbox;
+
     final UITreeLabel label = (UITreeLabel) component;
     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
+    final String text = StringUtils.defaultString((String) label.getValue());
+
+    if (listbox) {
+      writer.writeText(text);
+    } else {
+      writer.startElement(HtmlElements.LABEL, label);
+      writer.writeClassAttribute(Classes.create(label));
+      writer.writeStyleAttribute(createStyle(facesContext, label));
+      String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, label);
+      if (title != null) {
+        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+      }
 
-    writer.startElement(HtmlElements.LABEL, label);
-    writer.writeClassAttribute(Classes.create(label));
-    writer.writeStyleAttribute(createStyle(facesContext, label));
-    HtmlRendererUtils.renderTip(label, writer);
+      writer.writeText(text);
 
-    if (label.getValue() != null) {
-      writer.writeText((String) label.getValue());
+      writer.endElement(HtmlElements.LABEL);
     }
-    writer.endElement(HtmlElements.LABEL);
   }
 
   protected Style createStyle(FacesContext facesContext, UITreeLabel link) {
     return new Style(facesContext, link);
   }
-
 }

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxNodeRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxNodeRenderer.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxNodeRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxNodeRenderer.java Thu May 24 11:01:10 2012
@@ -18,20 +18,13 @@ package org.apache.myfaces.tobago.render
  */
 
 import org.apache.commons.lang.StringUtils;
-import org.apache.myfaces.tobago.component.Attributes;
-import org.apache.myfaces.tobago.component.UITreeLabel;
 import org.apache.myfaces.tobago.component.UITreeNode;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.event.TreeExpansionEvent;
 import org.apache.myfaces.tobago.event.TreeMarkedEvent;
 import org.apache.myfaces.tobago.internal.component.AbstractUITree;
-import org.apache.myfaces.tobago.internal.context.ResponseWriterDivider;
-import org.apache.myfaces.tobago.layout.Display;
-import org.apache.myfaces.tobago.layout.Measure;
 import org.apache.myfaces.tobago.model.TreeSelectable;
 import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
-import org.apache.myfaces.tobago.renderkit.css.Classes;
-import org.apache.myfaces.tobago.renderkit.css.Style;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
@@ -44,7 +37,6 @@ import javax.faces.component.NamingConta
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import java.io.IOException;
-import java.util.List;
 import java.util.Map;
 
 public class TreeListboxNodeRenderer extends CommandRendererBase {
@@ -116,86 +108,28 @@ public class TreeListboxNodeRenderer ext
   @Override
   public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
     final UITreeNode node = (UITreeNode) component;
-    final AbstractUITree tree = ComponentUtils.findAncestor(node, AbstractUITree.class);
-
     final boolean folder = node.isFolder();
-    final int level = node.getLevel();
     final String id = node.getClientId(facesContext);
     final boolean expanded = folder && node.isExpanded();
 
-    TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
-
-    if (level > 0) { // root will not rendered as an option
-      writer.startElement(HtmlElements.OPTION, null);
-      // todo: define where to store the selection of a tree, node.getValue() seems not to be a god place.
-      //        writer.writeAttribute(HtmlAttributes.VALUE, node.getValue().toString(), true); // XXX converter?
-      writer.writeIdAttribute(id);
-      writer.writeAttribute(HtmlAttributes.SELECTED, expanded);
-      writer.writeText("(" + level + ") " + getLabel(node));
-      if (folder) {
-        writer.writeText(" \u2192");
-      }
-      writer.endElement(HtmlElements.OPTION);
-    }
-
-    if (folder) {
-      boolean siblingMode = "siblingLeafOnly".equals(tree.getAttributes().get(Attributes.SELECTABLE));
-      ResponseWriterDivider divider = ResponseWriterDivider.getInstance(facesContext, TreeListboxRenderer.DIVIDER);
-      boolean alreadyExists = divider.activateBranch(facesContext);
-      writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
-      if (!alreadyExists) {
-        writer.startElement(HtmlElements.DIV, null);
-        writer.writeClassAttribute(Classes.create(tree, "level"));
-        Style levelStyle = new Style();
-        levelStyle.setLeft(Measure.valueOf(level * 160)); // xxx 160 should be configurable
-        writer.writeStyleAttribute(levelStyle);
-        // at the start of each div there is an empty and disabled select tag to show empty area.
-        // this is not needed for the 1st level.
-        if (level > 0) {
-          writer.startElement(HtmlElements.SELECT, null);
-          writer.writeAttribute(HtmlAttributes.DISABLED, true);
-          writer.writeAttribute(HtmlAttributes.SIZE, 2); // must be > 1, but the size comes from the layout
-          writer.writeClassAttribute(Classes.create(tree, "select"));
-          writer.endElement(HtmlElements.SELECT);
-        }
-      }
-
-      writer.startElement(HtmlElements.SELECT, node);
-      writer.writeIdAttribute(id + ComponentUtils.SUB_SEPARATOR + "select");
-      writer.writeClassAttribute(Classes.create(tree, "select"));
-      if (!expanded) {
-        Style selectStyle = new Style();
-        selectStyle.setDisplay(Display.NONE);
-      }
-      writer.writeAttribute(HtmlAttributes.SIZE, 2); // must be > 1, but the size comes from the layout
-      writer.writeAttribute(HtmlAttributes.MULTIPLE, siblingMode);
+    final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
 
-      // XXX insert options here
-      writer.startElement(HtmlElements.OPTGROUP, null);
-      writer.writeAttribute(HtmlAttributes.LABEL, getLabel(node), true);
-      writer.endElement(HtmlElements.OPTGROUP);
-    }
-  }
-
-  // XXX this is a hotfix, may be better calling the renderer?
-  private String getLabel(UITreeNode node) {
-    for (UIComponent component : (List<UIComponent>) node.getChildren()) {
-      if (component instanceof UITreeLabel) {
-        return "" + ((UITreeLabel) component).getValue();
-      }
-    }
-    return null;
+    writer.startElement(HtmlElements.OPTION, null);
+    // todo: define where to store the selection of a tree, node.getValue() seems not to be a god place.
+    //        writer.writeAttribute(HtmlAttributes.VALUE, node.getValue().toString(), true); // XXX converter?
+    writer.writeIdAttribute(id);
+    writer.writeAttribute(HtmlAttributes.SELECTED, expanded);
   }
 
   @Override
   public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
-    UITreeNode node = (UITreeNode) component;
-    boolean folder = node.isFolder();
+    final UITreeNode node = (UITreeNode) component;
+    final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
+    final boolean folder = node.isFolder();
+
     if (folder) {
-      TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
-      writer.endElement(HtmlElements.SELECT);
-      ResponseWriterDivider divider = ResponseWriterDivider.getInstance(facesContext, TreeListboxRenderer.DIVIDER);
-      divider.passivateBranch(facesContext);
+      writer.writeText(" \u2192"); // this is an right arrow →
     }
+    writer.endElement(HtmlElements.OPTION);
   }
 }

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxRenderer.java?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeListboxRenderer.java Thu May 24 11:01:10 2012
@@ -18,14 +18,15 @@ package org.apache.myfaces.tobago.render
  */
 
 import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UITreeLabel;
 import org.apache.myfaces.tobago.component.UITreeNode;
 import org.apache.myfaces.tobago.internal.component.AbstractUITree;
-import org.apache.myfaces.tobago.internal.context.ResponseWriterDivider;
 import org.apache.myfaces.tobago.layout.Measure;
 import org.apache.myfaces.tobago.renderkit.LayoutComponentRendererBase;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 import org.apache.myfaces.tobago.renderkit.css.Position;
 import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
 import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
@@ -37,13 +38,11 @@ import org.apache.myfaces.tobago.webapp.
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 public class TreeListboxRenderer extends LayoutComponentRendererBase {
 
-
-  public static final String DIVIDER = TreeListboxRenderer.class.getName() + "DIVIDER";
-
   public void prepareRender(FacesContext facesContext, UIComponent component) throws IOException {
     super.prepareRender(facesContext, component);
     setRendererTypeForCommandsAndNodes(component);
@@ -66,16 +65,21 @@ public class TreeListboxRenderer extends
   @Override
   public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
 
-    AbstractUITree tree = (AbstractUITree) component;
+    final AbstractUITree tree = (AbstractUITree) component;
+    final String clientId = tree.getClientId(facesContext);
+    final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
+    final Style style = new Style(facesContext, tree);
+    final Style scrollDivStyle = new Style();
 
-    String clientId = tree.getClientId(facesContext);
-    UIComponent root = tree.getRoot();
-
-    TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
+    writer.startElement(HtmlElements.DIV, tree);
+    scrollDivStyle.setWidth(Measure.valueOf(6 * 160)); // todo: depth * width of a select
+    scrollDivStyle.setHeight(style.getHeight() // todo: what, when there is no scrollbar?
+        .subtract(15)); // todo: scrollbar height
+    scrollDivStyle.setPosition(Position.ABSOLUTE);
+    writer.writeStyleAttribute(scrollDivStyle);
 
     writer.startElement(HtmlElements.DIV, tree);
     writer.writeClassAttribute(Classes.create(tree));
-    Style style = new Style(facesContext, tree);
     writer.writeStyleAttribute(style);
 
     writer.startElement(HtmlElements.INPUT, tree);
@@ -101,31 +105,89 @@ public class TreeListboxRenderer extends
       writer.endElement(HtmlElements.INPUT);
     }
 
-    RenderUtils.encode(facesContext, root);
+    List<Integer> thisLevel = new ArrayList<Integer>();
+    thisLevel.add(0);
+    List<Integer> nextLevel = new ArrayList<Integer>();
+    for (int level = 0; level < 7; level++) { // XXX not a fix value!!!
+
+      writer.startElement(HtmlElements.DIV, null);
+      writer.writeClassAttribute(Classes.create(tree, "level"));
+      Style levelStyle = new Style();
+      levelStyle.setLeft(Measure.valueOf(level * 160)); // xxx 160 should be configurable
+      writer.writeStyleAttribute(levelStyle);
+      // at the start of each div there is an empty and disabled select tag to show empty area.
+      // this is not needed for the 1st level.
+      if (level > 0) {
+        writer.startElement(HtmlElements.SELECT, null);
+        writer.writeAttribute(HtmlAttributes.DISABLED, true);
+        writer.writeAttribute(HtmlAttributes.SIZE, 9); // must be > 1, but the real size comes from the layout
+        writer.writeClassAttribute(Classes.create(tree, "select"));
+        writer.endElement(HtmlElements.SELECT);
+      }
+
+      for(Integer rowIndex : thisLevel) {
+        encodeSelectBox(facesContext, tree, writer, rowIndex, nextLevel);
+      }
+
+      thisLevel.clear();
+      List<Integer> swap = thisLevel;
+      thisLevel = nextLevel;
+      nextLevel = swap;
 
-    writer.startElement(HtmlElements.DIV, tree);
-    Style scrollDivStyle = new Style();
-    scrollDivStyle.setWidth(Measure.valueOf(6 * 160)); // todo: depth * width of a select 
-    scrollDivStyle.setHeight(style.getHeight() // todo: what, when there is no scrollbar? 
-        .subtract(15)); // todo: scrollbar height
-    scrollDivStyle.setPosition(Position.ABSOLUTE);
-    writer.writeStyleAttribute(scrollDivStyle);
-    
-    ResponseWriterDivider divider = ResponseWriterDivider.getInstance(facesContext, DIVIDER);
-    // write in all open branches the end tag.
-    while (divider.activateBranch(facesContext)) {
-      writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
       writer.endElement(HtmlElements.DIV);
     }
-    while (divider.passivateBranch(facesContext)) {
-    }  
-      
-    divider.writeOutAndCleanUp(facesContext);
-
-    writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
 
     writer.endElement(HtmlElements.DIV);
-    
     writer.endElement(HtmlElements.DIV);
+
+    tree.setRowIndex(-1);
+  }
+
+  private void encodeSelectBox(
+      FacesContext facesContext, AbstractUITree tree, TobagoResponseWriter writer,
+      int parentRowIndex, List<Integer> foldersRowIndices)
+      throws IOException {
+
+    tree.setRowIndex(parentRowIndex);
+
+    final UITreeNode node = ComponentUtils.findDescendant(tree, UITreeNode.class);
+    final String parentId = node.getClientId(facesContext);
+
+    writer.startElement(HtmlElements.SELECT, tree);
+    writer.writeClassAttribute(Classes.create(tree, "select"));
+    if (parentId != null) {
+      writer.writeAttribute(DataAttributes.TREEPARENT, parentId, false);
+    }
+
+    writer.writeAttribute(HtmlAttributes.SIZE, 9); // must be > 1, but the real size comes from the layout
+//    writer.writeAttribute(HtmlAttributes.MULTIPLE, siblingMode);
+
+    final UITreeLabel label = ComponentUtils.findDescendant(tree, UITreeLabel.class);
+    final Object labelValue = label.getValue();
+    if (labelValue != null) {
+      writer.startElement(HtmlElements.OPTGROUP, tree);
+      writer.writeAttribute(HtmlAttributes.LABEL, labelValue.toString(), true);
+      writer.endElement(HtmlElements.OPTGROUP);
+    }
+
+    final List<Integer> childrensRowIndices = tree.getChildrensRowIndices();
+
+    for (Integer rowIndex : childrensRowIndices) {
+      tree.setRowIndex(rowIndex);
+      if (!tree.isRowAvailable()) {
+        break;
+      }
+
+      for (UIComponent child : tree.getChildren()) {
+        RenderUtils.prepareRendererAll(facesContext, child);
+        RenderUtils.encode(facesContext, child);
+      }
+
+      if (tree.isFolder()) {
+        foldersRowIndices.add(rowIndex);
+      }
+    }
+
+    writer.endElement(HtmlElements.SELECT);
   }
 }

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js?rev=1342193&r1=1342192&r2=1342193&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js Thu May 24 11:01:10 2012
@@ -115,14 +115,13 @@ Tobago.Tree.init = function(elements) {
 
   listboxSelects.children("option").each(function() {
     var option = jQuery(this);
-    var optionId = option.attr("id");
-    var selectId = optionId + "::select";
-    var select = jQuery(Tobago.Utils.escapeClientId(selectId));
+    var select = option.closest(".tobago-treeListbox-level").next()
+        .find("[data-tobago-treeparent='" + option.attr("id") + "']");
     if (select.length == 1) {
-      option.data("select", select);
+      option.data("tobago-select", select);
     } else {
-      var empty = option.parent().parent().next().children(":first");
-      option.data("select", empty);
+      var empty = option.closest(".tobago-treeListbox-level").next().children(":first");
+      option.data("tobago-select", empty);
     }
   });
 
@@ -133,9 +132,9 @@ Tobago.Tree.init = function(elements) {
 
     jQuery(this).change(function() {
       jQuery(this).children("option:not(:selected)").each(function() {
-        jQuery(this).data("select").hide();
+        jQuery(this).data("tobago-select").hide();
       });
-      jQuery(this).children("option:selected").data("select").show();
+      jQuery(this).children("option:selected").data("tobago-select").show();
 
       // Deeper level (2nd and later) should only show the empty select tag.
       // The first child is the empty selection.