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 2016/04/07 10:12:11 UTC

svn commit: r1738103 - in /myfaces/tobago/branches/tobago-3.0.x: tobago-core/src/main/java/org/apache/myfaces/tobago/component/ tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/ tobago-core/src/main/java/org/apache/myfaces/tobago/...

Author: lofwyr
Date: Thu Apr  7 08:12:11 2016
New Revision: 1738103

URL: http://svn.apache.org/viewvc?rev=1738103&view=rev
Log:
TOBAGO-1502: Advanced tc:sheet support for Bootstrap
* two modes: column widths: auto vs. manual

Removed:
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/java/org/
Modified:
    myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/overview/OverviewController.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/JsonUtils.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/GridLayoutRenderer.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SheetRenderer.java
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/style/tobago.css
    myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/JsonUtilsUnitTest.java

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java Thu Apr  7 08:12:11 2016
@@ -251,7 +251,6 @@ public enum Attributes {
   validator,
   width,
   widthList,
-  widthListString,
   zIndex;
 
   private static final Logger LOG = LoggerFactory.getLogger(Attributes.class);

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java Thu Apr  7 08:12:11 2016
@@ -33,6 +33,7 @@ import org.apache.myfaces.tobago.event.S
 import org.apache.myfaces.tobago.internal.layout.Grid;
 import org.apache.myfaces.tobago.internal.layout.OriginCell;
 import org.apache.myfaces.tobago.layout.AutoLayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutToken;
 import org.apache.myfaces.tobago.layout.LayoutTokens;
 import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
 import org.apache.myfaces.tobago.model.ExpandedState;
@@ -50,6 +51,8 @@ import javax.faces.component.UIComponent
 import javax.faces.component.UINamingContainer;
 import javax.faces.context.FacesContext;
 import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
 import javax.faces.event.FacesEvent;
 import javax.faces.event.ListenerFor;
 import javax.faces.event.PhaseId;
@@ -61,7 +64,8 @@ import java.util.List;
 
 @ListenerFor(systemEventClass = PreRenderComponentEvent.class)
 public abstract class AbstractUISheet extends AbstractUIData
-    implements SheetStateChangeSource2, SortActionSource2, OnComponentPopulated, SupportsRenderedPartially, Visual {
+    implements SheetStateChangeSource2, SortActionSource2, OnComponentPopulated, SupportsRenderedPartially, Visual,
+        ComponentSystemEventListener {
 
   private static final Logger LOG = LoggerFactory.getLogger(AbstractUISheet.class);
 
@@ -70,8 +74,8 @@ public abstract class AbstractUISheet ex
   public static final String SORTER_ID = "sorter";
 
   private SheetState state;
-  private List<Integer> widthList;
   private transient LayoutTokens columnLayout;
+  private transient boolean autoLayout;
 
   private transient Grid headerGrid;
 
@@ -121,26 +125,35 @@ public abstract class AbstractUISheet ex
 
   public abstract String getColumns();
 
-  public LayoutTokens getColumnLayout() {
-    if (columnLayout == null) {
+  @Override
+  public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
+
+    if (event instanceof PreRenderComponentEvent) {
       final String columns = getColumns();
       if (columns != null) {
         columnLayout = LayoutTokens.parse(columns);
       }
+
+      autoLayout = true;
+      if (columnLayout != null) {
+        for (LayoutToken layoutToken : columnLayout.getTokens()) {
+          if (! (layoutToken instanceof AutoLayoutToken)) {
+            autoLayout = false;
+            break;
+          }
+        }
+      }
+
+      LOG.debug("autoLayout={}", autoLayout);
     }
+  }
+
+  public LayoutTokens getColumnLayout() {
     return columnLayout;
   }
 
-  /**
-   * Remove the (by user) resized column widths. An application may provide a button to access it.
-   * Since 1.0.26.
-   */
-  public void resetColumnWidths() {
-    final SheetState state = getState();
-    if (state != null) {
-      state.setColumnWidths(null);
-    }
-    getAttributes().remove(Attributes.widthListString.getName());
+  public boolean isAutoLayout() {
+    return autoLayout;
   }
 
   /**
@@ -294,21 +307,16 @@ public abstract class AbstractUISheet ex
   @Override
   public void processUpdates(final FacesContext context) {
     super.processUpdates(context);
-    updateSheetState(context);
-  }
 
-  private void updateSheetState(final FacesContext facesContext) {
-    final SheetState state = getSheetState(facesContext);
+    final SheetState state = getSheetState(context);
     if (state != null) {
       final List<Integer> list = (List<Integer>) ComponentUtils.getAttribute(this, Attributes.selectedListString);
       state.setSelectedRows(list != null ? list : Collections.<Integer>emptyList());
-      state.setColumnWidths(ComponentUtils.getStringAttribute(this, Attributes.widthListString));
       ComponentUtils.removeAttribute(this, Attributes.selectedListString);
       ComponentUtils.removeAttribute(this, Attributes.scrollPosition);
     }
   }
 
-
   @Override
   public Object saveState(final FacesContext context) {
     final Object[] saveState = new Object[2];
@@ -330,6 +338,8 @@ public abstract class AbstractUISheet ex
     return result;
   }
 
+  // TODO remove
+  @Deprecated
   public List<AbstractUIColumnBase> getRenderedColumns() {
     ArrayList<AbstractUIColumnBase> result = new ArrayList<AbstractUIColumnBase>();
     findColumns(this, result, false);
@@ -397,22 +407,9 @@ public abstract class AbstractUISheet ex
 
   public void init(FacesContext facesContext) {
     sort(facesContext, null);
-    ensureColumnWidthList();
     layoutHeader();
   }
 
-  private void ensureColumnWidthList() {
-
-    final List<AbstractUIColumnBase> allColumns = getAllColumns();
-    final  List<Integer> currentWidthList = new ArrayList<Integer>(allColumns.size() + 1);
-    for (int i = 0; i < allColumns.size(); i++) {
-      final AbstractUIColumnBase column = allColumns.get(i);
-      currentWidthList.add(null);
-    }
-
-    setWidthList(currentWidthList);
-  }
-
   private void layoutHeader() {
     final UIComponent header = getHeader();
     if (header == null) {
@@ -473,14 +470,6 @@ public abstract class AbstractUISheet ex
     removeFacesListener(listener);
   }
 
-  public List<Integer> getWidthList() {
-    return widthList;
-  }
-
-  public void setWidthList(final List<Integer> widthList) {
-    this.widthList = widthList;
-  }
-
   @Override
   public UIComponent findComponent(final String searchId) {
     return super.findComponent(stripRowIndex(searchId));

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java Thu Apr  7 08:12:11 2016
@@ -60,7 +60,7 @@ public interface SheetTagDeclaration
     extends HasIdBindingAndRendered, IsVisual, HasRenderedPartially, IsShowRoot, IsShowRootJunction, HasVar {
   /**
    * LayoutConstraints for column layout.
-   * Semicolon separated list of layout tokens ('&lt;x>*', '&lt;x>px' or '&lt;x>%').
+   * Semicolon separated list of layout tokens ('&lt;x>*', '&lt;x>px' or '&lt;x>%') or "auto"
    */
   @TagAttribute
   @UIComponentTagAttribute()

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java Thu Apr  7 08:12:11 2016
@@ -41,7 +41,7 @@ public class SheetState implements Seria
   private String sortedColumnId;
   private boolean ascending;
   private boolean toBeSorted;
-  private String columnWidths;
+  private List<Integer> columnWidths;
   private List<Integer> selectedRows;
   private ScrollPosition scrollPosition;
   private ExpandedState expandedState;
@@ -106,11 +106,11 @@ public class SheetState implements Seria
     }
   }
 
-  public String getColumnWidths() {
+  public List<Integer> getColumnWidths() {
     return columnWidths;
   }
 
-  public void setColumnWidths(final String columnWidths) {
+  public void setColumnWidths(final List<Integer> columnWidths) {
     this.columnWidths = columnWidths;
   }
 

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/overview/OverviewController.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/overview/OverviewController.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/overview/OverviewController.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/overview/OverviewController.java Thu Apr  7 08:12:11 2016
@@ -175,7 +175,7 @@ public class OverviewController implemen
   public void resetColumnWidths(final ActionEvent event) {
     final UISheet sheet = (UISheet) event.getComponent().findComponent("sheet");
     if (sheet != null) {
-      sheet.resetColumnWidths();
+      sheet.getState().setColumnWidths(null);
     } else {
       LOG.warn("Didn't find sheet component!");
     }

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java Thu Apr  7 08:12:11 2016
@@ -36,6 +36,8 @@ public enum TobagoClass implements CssIt
   ALIGN_ITEMS__FLEX_START("alignItems-flexStart"),
   ALIGN_ITEMS__STRETCH("alignItems-stretch"),
   DROPDOWN_SUBMENU("dropdown-submenu"),
+  TABLE_LAYOUT__FIXED("tableLayout-fixed"),
+
   FLEX_LAYOUT("tobago-flexLayout"),
   LABEL("tobago-label"),
   MENU_BAR("tobago-menuBar"),

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/JsonUtils.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/JsonUtils.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/JsonUtils.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/JsonUtils.java Thu Apr  7 08:12:11 2016
@@ -20,11 +20,23 @@
 package org.apache.myfaces.tobago.renderkit.html;
 
 import org.apache.myfaces.tobago.internal.context.DateTimeI18n;
+import org.apache.myfaces.tobago.layout.AutoLayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.MeasureLayoutToken;
+import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 public class JsonUtils {
 
+  private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);
+
   private JsonUtils() {
   }
 
@@ -51,6 +63,19 @@ public class JsonUtils {
     builder.append("]");
   }
 
+  public static void encode(StringBuilder builder, List<Integer> value) {
+    builder.append("[");
+    boolean colon = false;
+    for (final Integer item : value) {
+      if (colon) {
+        builder.append(",");
+      }
+      builder.append(item);
+      colon = true;
+    }
+    builder.append("]");
+  }
+
   static void encode(final StringBuilder builder, final String name, final Boolean value) {
     builder.append("\"");
     builder.append(name);
@@ -207,4 +232,57 @@ public class JsonUtils {
     encode(builder, strings);
     return builder.toString();
   }
+
+  public static String encode(final List<Integer> integers) {
+    if (integers == null) {
+      return null;
+    }
+    final StringBuilder builder = new StringBuilder();
+    encode(builder, integers);
+    return builder.toString();
+  }
+
+  public static void encode(final LayoutTokens bankHeads, final StringBuilder builder) {
+    builder.append("[");
+    for (final LayoutToken token : bankHeads.getTokens()) {
+      if (token instanceof RelativeLayoutToken) {
+        final int factor = ((RelativeLayoutToken) token).getFactor();
+        builder.append(factor);
+      } else if (token instanceof AutoLayoutToken) {
+        builder.append("\"auto\"");
+      } else if (token instanceof MeasureLayoutToken) {
+        builder.append("{\"measure\":\"");
+        builder.append(((MeasureLayoutToken) token).getMeasure());
+        builder.append("\"}");
+      } else {
+        LOG.warn("Not supported: " + token);
+      }
+      builder.append(',');
+    }
+    if (builder.charAt(builder.length() - 1) == ',') {
+      builder.deleteCharAt(builder.length() - 1);
+    }
+    builder.append("]");
+  }
+
+  public static List<Integer> decodeIntegerArray(String json) {
+    json = json.trim();
+    if (json.length() < 2 || json.charAt(0) != '[' || json.charAt(json.length() - 1) != ']') {
+      LOG.error("Can't parse JSON array: no surrounding square brackets []: '{}'", json);
+      return null;
+    }
+    json = json.substring(1, json.length() - 1);
+    final List<Integer> result = new ArrayList<Integer>();
+    final StringTokenizer tokenizer = new StringTokenizer(json, ",");
+    while (tokenizer.hasMoreTokens()) {
+      final String token = tokenizer.nextToken().trim();
+      try {
+        result.add(Integer.parseInt(token));
+      } catch (NumberFormatException e) {
+        LOG.error("Can't parse JSON array: not an integer token: '{}'", token);
+        // ignoring so far
+      }
+    }
+    return result;
+  }
 }

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/GridLayoutRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/GridLayoutRenderer.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/GridLayoutRenderer.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/GridLayoutRenderer.java Thu Apr  7 08:12:11 2016
@@ -24,18 +24,16 @@ import org.apache.myfaces.tobago.interna
 import org.apache.myfaces.tobago.internal.layout.Cell;
 import org.apache.myfaces.tobago.internal.layout.Grid;
 import org.apache.myfaces.tobago.internal.layout.OriginCell;
-import org.apache.myfaces.tobago.layout.AutoLayoutToken;
 import org.apache.myfaces.tobago.layout.LayoutToken;
 import org.apache.myfaces.tobago.layout.LayoutTokens;
 import org.apache.myfaces.tobago.layout.Measure;
-import org.apache.myfaces.tobago.layout.MeasureLayoutToken;
-import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 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.HtmlRoleValues;
+import org.apache.myfaces.tobago.renderkit.html.JsonUtils;
 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
 import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
 import org.apache.myfaces.tobago.util.ComponentUtils;
@@ -65,11 +63,11 @@ public class GridLayoutRenderer extends
     final StringBuilder builder = new StringBuilder();
 
     builder.append("{\"columns\":");
-    jsonLayout(gridLayout.getGrid().getColumns(), builder);
+    JsonUtils.encode(gridLayout.getGrid().getColumns(), builder);
     builder.append(",");
 
     builder.append("\"rows\":");
-    jsonLayout(gridLayout.getGrid().getRows(), builder);
+    JsonUtils.encode(gridLayout.getGrid().getRows(), builder);
     builder.append("}");
 
     writer.writeAttribute(DataAttributes.LAYOUT, builder.toString(), true);
@@ -84,29 +82,6 @@ public class GridLayoutRenderer extends
     writer.startElement(HtmlElements.TBODY);
   }
 
-  private void jsonLayout(final LayoutTokens bankHeads, final StringBuilder builder) {
-    builder.append("[");
-    for (final LayoutToken token : bankHeads.getTokens()) {
-      if (token instanceof RelativeLayoutToken) {
-        final int factor = ((RelativeLayoutToken) token).getFactor();
-        builder.append(factor);
-      } else if (token instanceof AutoLayoutToken) {
-        builder.append("\"auto\"");
-      } else if (token instanceof MeasureLayoutToken) {
-        builder.append("{\"measure\":\"");
-        builder.append(((MeasureLayoutToken) token).getMeasure());
-        builder.append("\"}");
-      } else {
-        LOG.warn("Not supported: " + token);
-      }
-      builder.append(',');
-    }
-    if (builder.charAt(builder.length() - 1) == ',') {
-      builder.deleteCharAt(builder.length() - 1);
-    }
-    builder.append("]");
-  }
-
   @Override
   public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
     final AbstractUIGridLayout gridLayout = (AbstractUIGridLayout) component;

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SheetRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SheetRenderer.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SheetRenderer.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SheetRenderer.java Thu Apr  7 08:12:11 2016
@@ -95,10 +95,10 @@ public class SheetRenderer extends Rende
 
   private static final Logger LOG = LoggerFactory.getLogger(SheetRenderer.class);
 
-  protected static final String WIDTHS = ComponentUtils.SUB_SEPARATOR + "widths";
-  protected static final String SCROLL_POSITION = ComponentUtils.SUB_SEPARATOR + "scrollPosition";
-  protected static final String SELECTED = ComponentUtils.SUB_SEPARATOR + "selected";
-  protected static final String SELECTOR_DROPDOWN = ComponentUtils.SUB_SEPARATOR + "selectorDropdown";
+  private static final String SUFFIX_WIDTHS = ComponentUtils.SUB_SEPARATOR + "widths";
+  private static final String SUFFIX_SCROLL_POSITION = ComponentUtils.SUB_SEPARATOR + "scrollPosition";
+  private static final String SUFFIX_SELECTED = ComponentUtils.SUB_SEPARATOR + "selected";
+  private static final String SUFFIX_SELECTOR_DROPDOWN = ComponentUtils.SUB_SEPARATOR + "selectorDropdown";
 
   @Override
   public void decode(final FacesContext facesContext, final UIComponent component) {
@@ -106,16 +106,14 @@ public class SheetRenderer extends Rende
     final UISheet sheet = (UISheet) component;
     final String clientId = sheet.getClientId(facesContext);
 
-    String key = clientId + WIDTHS;
+    String key = clientId + SUFFIX_WIDTHS;
     final Map requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
     if (requestParameterMap.containsKey(key)) {
       final String widths = (String) requestParameterMap.get(key);
-      if (widths.trim().length() > 0) {
-        ComponentUtils.setAttribute(sheet, Attributes.widthListString, widths);
-      }
+      sheet.getState().setColumnWidths(JsonUtils.decodeIntegerArray(widths));
     }
 
-    key = clientId + SELECTED;
+    key = clientId + SUFFIX_SELECTED;
     if (requestParameterMap.containsKey(key)) {
       final String selected = (String) requestParameterMap.get(key);
       if (LOG.isDebugEnabled()) {
@@ -132,7 +130,8 @@ public class SheetRenderer extends Rende
       ComponentUtils.setAttribute(sheet, Attributes.selectedListString, selectedRows);
     }
 
-    final String value = facesContext.getExternalContext().getRequestParameterMap().get(clientId + SCROLL_POSITION);
+    final String value
+        = facesContext.getExternalContext().getRequestParameterMap().get(clientId + SUFFIX_SCROLL_POSITION);
     if (value != null) {
       sheet.getState().getScrollPosition().update(value);
     }
@@ -195,6 +194,20 @@ public class SheetRenderer extends Rende
         ComponentUtils.evaluateClientIds(facesContext, sheet, sheet.getRenderedPartially()), false);
     writer.writeAttribute(DataAttributes.SELECTION_MODE, sheet.getSelectable().name(), false);
     writer.writeAttribute(DataAttributes.FIRST, Integer.toString(sheet.getFirst()), false);
+    final StringBuilder builder = new StringBuilder();
+
+    final boolean autoLayout = sheet.isAutoLayout();
+    if (!autoLayout) {
+      builder.append("{\"columns\":");
+      JsonUtils.encode(sheet.getColumnLayout(), builder);
+      builder.append("}");
+      writer.writeAttribute(DataAttributes.LAYOUT, builder.toString(), true);
+    }
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext context, final UIComponent component) throws IOException {
+    // DO Nothing
   }
 
   @Override
@@ -208,21 +221,26 @@ public class SheetRenderer extends Rende
     final Selectable selectable = sheet.getSelectable();
     final Application application = facesContext.getApplication();
     final SheetState state = sheet.getSheetState(facesContext);
-    final List<Integer> columnWidths = sheet.getWidthList();
+    final List<Integer> columnWidths = sheet.getState().getColumnWidths();
     final List<Integer> selectedRows = getSelectedRows(sheet, state);
     final List<AbstractUIColumnBase> renderedColumnList = sheet.getRenderedColumns();
+    final List<AbstractUIColumnBase> allColumnList = sheet.getAllColumns();
+    final boolean showHeader = sheet.isShowHeader();
+    final boolean autoLayout = sheet.isAutoLayout();
 
-    writer.startElement(HtmlElements.INPUT);
-    writer.writeIdAttribute(sheetId + WIDTHS);
-    writer.writeNameAttribute(sheetId + WIDTHS);
-    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
-    writer.writeAttribute(HtmlAttributes.VALUE, StringUtils.joinWithSurroundingSeparator(columnWidths), false);
-    writer.endElement(HtmlElements.INPUT);
+    if (!autoLayout) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeIdAttribute(sheetId + SUFFIX_WIDTHS);
+      writer.writeNameAttribute(sheetId + SUFFIX_WIDTHS);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      writer.writeAttribute(HtmlAttributes.VALUE, JsonUtils.encode(columnWidths), false);
+      writer.endElement(HtmlElements.INPUT);
+    }
 
     final String clientId = sheet.getClientId(facesContext);
     writer.startElement(HtmlElements.INPUT);
-    writer.writeIdAttribute(clientId + SCROLL_POSITION);
-    writer.writeNameAttribute(clientId + SCROLL_POSITION);
+    writer.writeIdAttribute(clientId + SUFFIX_SCROLL_POSITION);
+    writer.writeNameAttribute(clientId + SUFFIX_SCROLL_POSITION);
     writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
     writer.writeAttribute(HtmlAttributes.VALUE, sheet.getState().getScrollPosition().encode(), false);
     writer.writeAttribute(DataAttributes.SCROLL_POSITION, Boolean.TRUE.toString(), true);
@@ -230,8 +248,8 @@ public class SheetRenderer extends Rende
 
     if (selectable != Selectable.none) {
       writer.startElement(HtmlElements.INPUT);
-      writer.writeIdAttribute(sheetId + SELECTED);
-      writer.writeNameAttribute(sheetId + SELECTED);
+      writer.writeIdAttribute(sheetId + SUFFIX_SELECTED);
+      writer.writeNameAttribute(sheetId + SUFFIX_SELECTED);
       writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
       writer.writeAttribute(
           HtmlAttributes.VALUE, StringUtils.joinWithSurroundingSeparator(selectedRows), true);
@@ -245,12 +263,27 @@ public class SheetRenderer extends Rende
       expandedValue = new StringBuilder(",");
     }
 
-    final boolean showHeader = sheet.isShowHeader();
-
 // BEGIN RENDER BODY CONTENT
 
-    if (showHeader) {
-      renderColumnHeaders(facesContext, sheet, writer, renderedColumnList);
+    if (showHeader && !autoLayout) {
+      // if no autoLayout, we render the header in a separate table.
+
+      writer.startElement(HtmlElements.HEADER);
+      writer.writeClassAttribute(Classes.create(sheet, "header"));
+      writer.startElement(HtmlElements.TABLE);
+      writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
+      writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
+      writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
+      writer.writeClassAttribute(Classes.create(sheet, "headerTable"),
+          BootstrapClass.TABLE, BootstrapClass.TABLE_BORDERED, TobagoClass.TABLE_LAYOUT__FIXED);
+
+      writeColgroup(writer, columnWidths, allColumnList);
+
+      writer.startElement(HtmlElements.TBODY);
+      encodeHeaderRows(facesContext, sheet, writer, renderedColumnList);
+      writer.endElement(HtmlElements.TBODY);
+      writer.endElement(HtmlElements.TABLE);
+      writer.endElement(HtmlElements.HEADER);
     }
 
     writer.startElement(HtmlElements.DIV);
@@ -266,9 +299,16 @@ public class SheetRenderer extends Rende
         BootstrapClass.TABLE,
         BootstrapClass.TABLE_BORDERED,
         BootstrapClass.TABLE_SM,
-        selectable != Selectable.none ? BootstrapClass.TABLE_HOVER : null);
+        selectable != Selectable.none ? BootstrapClass.TABLE_HOVER : null,
+        autoLayout ? null : TobagoClass.TABLE_LAYOUT__FIXED);
 
-    writeColgroup(writer, columnWidths);
+    if (autoLayout) {
+      writer.startElement(HtmlElements.THEAD);
+      encodeHeaderRows(facesContext, sheet, writer, renderedColumnList);
+      writer.endElement(HtmlElements.THEAD);
+    } else {
+      writeColgroup(writer, columnWidths, allColumnList);
+    }
 
     // Print the Content
 
@@ -276,6 +316,8 @@ public class SheetRenderer extends Rende
       LOG.debug("first = " + sheet.getFirst() + "   rows = " + sheet.getRows());
     }
 
+    writer.startElement(HtmlElements.TBODY);
+
     final String var = sheet.getVar();
 
     boolean emptySheet = true;
@@ -372,7 +414,7 @@ public class SheetRenderer extends Rende
         if (column instanceof UIColumnSelector) {
           UIColumnSelector selector = (UIColumnSelector) column;
           writer.startElement(HtmlElements.INPUT);
-          if (sheet.getSelectable().isSingle()) {
+          if (selectable.isSingle()) {
             writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.RADIO);
           } else {
             writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
@@ -393,12 +435,14 @@ public class SheetRenderer extends Rende
         writer.endElement(HtmlElements.TD);
       }
 
-      writer.startElement(HtmlElements.TD);
-      writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
+      if (!autoLayout) {
+        writer.startElement(HtmlElements.TD);
+        writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
 //      writer.write("&nbsp;");
-      writer.startElement(HtmlElements.DIV);
-      writer.endElement(HtmlElements.DIV);
-      writer.endElement(HtmlElements.TD);
+        writer.startElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.TD);
+      }
 
       writer.endElement(HtmlElements.TR);
     }
@@ -421,15 +465,19 @@ public class SheetRenderer extends Rende
         writer.endElement(HtmlElements.DIV);
         writer.endElement(HtmlElements.TD);
       }
-      writer.startElement(HtmlElements.TD);
-      writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
+      if (!autoLayout) {
+        writer.startElement(HtmlElements.TD);
+        writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
 //      writer.write("&nbsp;");
-      writer.startElement(HtmlElements.DIV);
-      writer.endElement(HtmlElements.DIV);
-      writer.endElement(HtmlElements.TD);
+        writer.startElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.TD);
+      }
       writer.endElement(HtmlElements.TR);
     }
 
+    writer.endElement(HtmlElements.TBODY);
+
     writer.endElement(HtmlElements.TABLE);
     writer.endElement(HtmlElements.DIV);
 
@@ -627,155 +675,20 @@ public class SheetRenderer extends Rende
     writer.endElement(HtmlElements.DIV);
   }
 
-  private void writeColgroup(final TobagoResponseWriter writer, final List<Integer> columnWidths) throws IOException {
-    if (columnWidths != null) {
-      writer.startElement(HtmlElements.COLGROUP);
-      for (final Integer columnWidth : columnWidths) {
-        writeCol(writer, columnWidth);
-      }
-      writeCol(writer, 0); // extra entry for resizing...
-      // TODO: replace 0 later
-      // TODO: the value should be added to the list
-      writer.endElement(HtmlElements.COLGROUP);
-    }
-  }
-
-  private void writeCol(final TobagoResponseWriter writer, final Integer columnWidth) throws IOException {
-    writer.startElement(HtmlElements.COL);
-    writer.writeAttribute(HtmlAttributes.WIDTH, columnWidth);
-    writer.endElement(HtmlElements.COL);
-  }
-
-  /**
-   * Differ between simple content and complex content.
-   * Decide if the content of a cell needs usually the whole possible space or
-   * is the character of the content like flowing text.
-   * In the second case, the style usually sets a padding.<br/>
-   * Pure is needed for &lt;tc:panel>,  &lt;tc:in>, etc.<br/>
-   * Pure is not needed for  &lt;tc:out> and &lt;tc:link>
-   */
-  private boolean isPure(final UIColumn column) {
-    for (final UIComponent child : column.getChildren()) {
-      if (!(child instanceof UIOut) && !(child instanceof UILink)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private Markup markupForLeftCenterRight(final ShowPosition position) {
-    switch (position) {
-      case left:
-        return Markup.LEFT;
-      case center:
-        return Markup.CENTER;
-      case right:
-        return Markup.RIGHT;
-      default:
-        return Markup.NULL;
-    }
-  }
-
-  @Override
-  public boolean getRendersChildren() {
-    return true;
-  }
-
-  private List<Integer> getSelectedRows(final UISheet data, final SheetState state) {
-    List<Integer> selected = (List<Integer>) ComponentUtils.getAttribute(data, Attributes.selectedListString);
-    if (selected == null && state != null) {
-      selected = state.getSelectedRows();
-    }
-    if (selected == null) {
-      selected = Collections.emptyList();
-    }
-    return selected;
-  }
-
-  private void encodeLink(
-      final FacesContext facesContext, final UISheet data, final Application application,
-      final boolean disabled, final PageAction action, Integer target, Icons icon, CssItem liClass)
-      throws IOException {
-
-    final String facet = action == PageAction.TO_PAGE || action == PageAction.TO_ROW
-        ? action.getToken() + "-" + target
-        : action.getToken();
-    final UICommand command = ensurePagingCommand(application, data, facet, action, disabled);
-    if (target != null) {
-      ComponentUtils.setAttribute(command, Attributes.pagingTarget, target);
-    }
-    command.setRenderedPartially(new String[]{data.getId()});
-
-    final Locale locale = facesContext.getViewRoot().getLocale();
-    final String message = ResourceManagerUtils.getPropertyNotNull(facesContext, "tobago", "sheet" + action.getToken());
-    final String tip = new MessageFormat(message, locale).format(new Integer[]{target}); // needed fot ToPage
-
-    final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
-    writer.startElement(HtmlElements.LI);
-    writer.writeClassAttribute(liClass, disabled ? BootstrapClass.DISABLED : null, BootstrapClass.PAGE_ITEM);
-    writer.startElement(HtmlElements.A);
-    writer.writeClassAttribute(BootstrapClass.PAGE_LINK);
-    writer.writeAttribute(HtmlAttributes.HREF, "#", false);
-    writer.writeIdAttribute(command.getClientId(facesContext));
-    writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
-    if (!disabled) {
-      final CommandMap map = new CommandMap(new Command(facesContext, command));
-      writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), true);
-    }
-    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
-    if (icon != null) {
-      writer.writeIcon(icon);
-    } else {
-      writer.writeText(String.valueOf(target));
-    }
-    writer.endElement(HtmlElements.A);
-    writer.endElement(HtmlElements.LI);
-  }
-
-  // TODO sheet.getColumnLayout() may return the wrong number of column...
-  // TODO
-  // TODO
-
-  private void renderColumnHeaders(
+  private void encodeHeaderRows(
       final FacesContext facesContext, final UISheet sheet, final TobagoResponseWriter writer,
       final List<AbstractUIColumnBase> renderedColumnList)
       throws IOException {
 
     final Selectable selectable = sheet.getSelectable();
-
     final Grid grid = sheet.getHeaderGrid();
-    if (grid == null) {
-      LOG.warn("Can't render column headers, because grid == null. One reason can be, the you use nested sheets. "
-          + "The inner sheet ensureHeader() will be called outside the iterating over the rows. "
-          + "Nesting sheet is currently not supported.");
-      return;
-    }
-    final List<Integer> columnWidths = sheet.getWidthList();
-
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("*****************************************************");
-      LOG.debug("" + grid);
-      LOG.debug("*****************************************************");
-    }
+    final boolean autoLayout = sheet.isAutoLayout();
 
-    writer.startElement(HtmlElements.HEADER);
-    writer.writeClassAttribute(Classes.create(sheet, "header"));
-    writer.startElement(HtmlElements.TABLE);
-    writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
-    writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
-    writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
-    writer.writeClassAttribute(
-        Classes.create(sheet, "headerTable"), BootstrapClass.TABLE, BootstrapClass.TABLE_BORDERED);
-
-    writeColgroup(writer, columnWidths);
-
-    writer.startElement(HtmlElements.TBODY);
     for (int i = 0; i < grid.getRowCount(); i++) {
       writer.startElement(HtmlElements.TR);
       for (int j = 0; j < grid.getColumnCount(); j++) {
         final Cell cell = grid.getCell(j, i);
         if (cell instanceof OriginCell) {
-//          writer.startElement(HtmlElements.TD, null);
           writer.startElement(HtmlElements.TH);
           if (cell.getColumnSpan() > 1) {
             writer.writeAttribute(HtmlAttributes.COLSPAN, cell.getColumnSpan());
@@ -793,7 +706,7 @@ public class SheetRenderer extends Rende
           final AbstractUIColumnBase column = renderedColumnList.get(j);
           Icons sorterIcon = null;
           Markup markup = Markup.NULL;
-           String tip = ComponentUtils.getStringAttribute(column, Attributes.tip);
+          String tip = ComponentUtils.getStringAttribute(column, Attributes.tip);
           // sorter icons should only displayed when there is only 1 column and not input
           if (cell.getColumnSpan() == 1 && cellComponent instanceof UIOut) {
             final boolean sortable = ComponentUtils.getBooleanAttribute(column, Attributes.sortable);
@@ -863,14 +776,14 @@ public class SheetRenderer extends Rende
             writer.writeClassAttribute(
                 BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY, BootstrapClass.DROPDOWN_TOGGLE);
             writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
-            writer.writeIdAttribute(sheet.getClientId(facesContext) + SELECTOR_DROPDOWN);
+            writer.writeIdAttribute(sheet.getClientId(facesContext) + SUFFIX_SELECTOR_DROPDOWN);
             writer.writeAttribute(DataAttributes.TOGGLE, "dropdown", false);
             writer.writeAttribute(Arias.HASPOPUP, Boolean.TRUE.toString(), false);
             writer.writeAttribute(Arias.EXPANDED, Boolean.FALSE.toString(), false);
             writer.endElement(HtmlElements.BUTTON);
             writer.startElement(HtmlElements.DIV);
             writer.writeClassAttribute(BootstrapClass.DROPDOWN_MENU);
-            writer.writeAttribute(Arias.LABELLEDBY, sheet.getClientId(facesContext) + SELECTOR_DROPDOWN, false);
+            writer.writeAttribute(Arias.LABELLEDBY, sheet.getClientId(facesContext) + SUFFIX_SELECTOR_DROPDOWN, false);
             writer.startElement(HtmlElements.BUTTON);
             writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
             writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
@@ -887,7 +800,8 @@ public class SheetRenderer extends Rende
             writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
             writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
             writer.writeAttribute(DataAttributes.COMMAND, "sheetToggleAll", false);
-            writer.writeText(ResourceManagerUtils.getPropertyNotNull(facesContext, "tobago", "sheetMenuToggleselect"));
+            writer
+                .writeText(ResourceManagerUtils.getPropertyNotNull(facesContext, "tobago", "sheetMenuToggleselect"));
             writer.endElement(HtmlElements.BUTTON);
             writer.endElement(HtmlElements.DIV);
             writer.endElement(HtmlElements.DIV);
@@ -922,42 +836,147 @@ public class SheetRenderer extends Rende
           }
           writer.endElement(HtmlElements.DIV);
 
-//          writer.endElement(HtmlElements.TD);
           writer.endElement(HtmlElements.TH);
         }
       }
-      // add a filler column
-//      writer.startElement(HtmlElements.TD, null);
-      writer.startElement(HtmlElements.TH);
-      writer.startElement(HtmlElements.DIV);
-      // todo: is the filler class needed here?
-      writer.writeClassAttribute(Classes.create(sheet, "headerCell", Markup.FILLER));
-      writer.startElement(HtmlElements.SPAN);
-      writer.writeClassAttribute(Classes.create(sheet, "header"));
-      final Style headerStyle = new Style();
-      headerStyle.setHeight(Measure.valueOf(14)); // XXX todo
-      writer.writeStyleAttribute(headerStyle);
-      writer.endElement(HtmlElements.SPAN);
-      writer.endElement(HtmlElements.DIV);
-//      writer.endElement(HtmlElements.TD);
-      writer.endElement(HtmlElements.TH);
+      if (!autoLayout) {
+        // add a filler column
+        writer.startElement(HtmlElements.TH);
+        writer.startElement(HtmlElements.DIV);
+        // todo: is the filler class needed here?
+        writer.writeClassAttribute(Classes.create(sheet, "headerCell", Markup.FILLER));
+        writer.startElement(HtmlElements.SPAN);
+        writer.writeClassAttribute(Classes.create(sheet, "header"));
+        final Style headerStyle = new Style();
+        headerStyle.setHeight(Measure.valueOf(14)); // XXX todo
+        writer.writeStyleAttribute(headerStyle);
+        writer.endElement(HtmlElements.SPAN);
+        writer.endElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.TH);
+      }
 
       writer.endElement(HtmlElements.TR);
     }
-    writer.endElement(HtmlElements.TBODY);
-    writer.endElement(HtmlElements.TABLE);
-    writer.endElement(HtmlElements.HEADER);
   }
 
+  private void writeColgroup(
+      final TobagoResponseWriter writer, final List<Integer> columnWidths,
+      final List<AbstractUIColumnBase> columnList) throws IOException {
+    writer.startElement(HtmlElements.COLGROUP);
+    for (int i = 0; i < columnList.size(); i++) {
+      final AbstractUIColumnBase column =  columnList.get(i);
+      if (column.isRendered()) {
+        writeCol(writer, columnWidths != null ? columnWidths.get(i) : null);
+      }
+    }
+    writeCol(writer, null); // extra entry for resizing...
+    // TODO: the value should be added to the list
+    writer.endElement(HtmlElements.COLGROUP);
+  }
+
+  private void writeCol(final TobagoResponseWriter writer, final Integer columnWidth) throws IOException {
+    writer.startElement(HtmlElements.COL);
+    writer.writeAttribute(HtmlAttributes.WIDTH, columnWidth);
+    writer.endElement(HtmlElements.COL);
+  }
+
+  /**
+   * Differ between simple content and complex content.
+   * Decide if the content of a cell needs usually the whole possible space or
+   * is the character of the content like flowing text.
+   * In the second case, the style usually sets a padding.<br/>
+   * Pure is needed for &lt;tc:panel>,  &lt;tc:in>, etc.<br/>
+   * Pure is not needed for  &lt;tc:out> and &lt;tc:link>
+   */
+  private boolean isPure(final UIColumn column) {
+    for (final UIComponent child : column.getChildren()) {
+      if (!(child instanceof UIOut) && !(child instanceof UILink)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private Markup markupForLeftCenterRight(final ShowPosition position) {
+    switch (position) {
+      case left:
+        return Markup.LEFT;
+      case center:
+        return Markup.CENTER;
+      case right:
+        return Markup.RIGHT;
+      default:
+        return Markup.NULL;
+    }
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  private List<Integer> getSelectedRows(final UISheet data, final SheetState state) {
+    List<Integer> selected = (List<Integer>) ComponentUtils.getAttribute(data, Attributes.selectedListString);
+    if (selected == null && state != null) {
+      selected = state.getSelectedRows();
+    }
+    if (selected == null) {
+      selected = Collections.emptyList();
+    }
+    return selected;
+  }
+
+  private void encodeLink(
+      final FacesContext facesContext, final UISheet data, final Application application,
+      final boolean disabled, final PageAction action, Integer target, Icons icon, CssItem liClass)
+      throws IOException {
+
+    final String facet = action == PageAction.TO_PAGE || action == PageAction.TO_ROW
+        ? action.getToken() + "-" + target
+        : action.getToken();
+    final UICommand command = ensurePagingCommand(application, data, facet, action, disabled);
+    if (target != null) {
+      ComponentUtils.setAttribute(command, Attributes.pagingTarget, target);
+    }
+    command.setRenderedPartially(new String[]{data.getId()});
+
+    final Locale locale = facesContext.getViewRoot().getLocale();
+    final String message = ResourceManagerUtils.getPropertyNotNull(facesContext, "tobago", "sheet" + action.getToken());
+    final String tip = new MessageFormat(message, locale).format(new Integer[]{target}); // needed fot ToPage
+
+    final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
+    writer.startElement(HtmlElements.LI);
+    writer.writeClassAttribute(liClass, disabled ? BootstrapClass.DISABLED : null, BootstrapClass.PAGE_ITEM);
+    writer.startElement(HtmlElements.A);
+    writer.writeClassAttribute(BootstrapClass.PAGE_LINK);
+    writer.writeAttribute(HtmlAttributes.HREF, "#", false);
+    writer.writeIdAttribute(command.getClientId(facesContext));
+    writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+    if (!disabled) {
+      final CommandMap map = new CommandMap(new Command(facesContext, command));
+      writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), true);
+    }
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    if (icon != null) {
+      writer.writeIcon(icon);
+    } else {
+      writer.writeText(String.valueOf(target));
+    }
+    writer.endElement(HtmlElements.A);
+    writer.endElement(HtmlElements.LI);
+  }
+
+  // TODO sheet.getColumnLayout() may return the wrong number of column...
+  // TODO
+  // TODO
+
   private void encodeResizing(final TobagoResponseWriter writer, final AbstractUISheet sheet, final int columnIndex)
       throws IOException {
-/* TBD: turned off in the moment
-    writer.startElement(HtmlElements.SPAN, null);
+    writer.startElement(HtmlElements.SPAN);
     writer.writeClassAttribute(Classes.create(sheet, "headerResize"));
     writer.writeAttribute(DataAttributes.COLUMN_INDEX, Integer.toString(columnIndex), false);
     writer.write("&nbsp;&nbsp;"); // is needed for IE
     writer.endElement(HtmlElements.SPAN);
-*/
   }
 
   private void encodeDirectPagingLinks(
@@ -1053,12 +1072,7 @@ public class SheetRenderer extends Rende
     return command;
   }
 
-  @Override
-  public void encodeChildren(final FacesContext context, final UIComponent component) throws IOException {
-    // DO Nothing
-  }
-
-  public static boolean renderSheetCommands(
+  private static boolean renderSheetCommands(
       final UISheet sheet, final FacesContext facesContext, final TobagoResponseWriter writer) throws IOException {
     CommandMap commandMap = null;
     for (final UIComponent child : sheet.getChildren()) {

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js Thu Apr  7 08:12:11 2016
@@ -61,12 +61,6 @@ Tobago.Sheet.init = function(elements) {
         dblclick != undefined ? dblclick.partially: undefined,
         sheet.data("tobago-partial-ids")); // type array
 
-    // cell widths
-    var thead = sheet.find("> .tobago-sheet-body > table.tobago-sheet-fixHeader > thead");
-    var count = thead.find("tr:last > th").length;
-    sheet.find("> .tobago-sheet-body > table > thead > tr:last > th, > .tobago-sheet-body > table > tbody > tr > td")
-        .css("width", 100.0/count + "%");
-
     //////////////////////////////////////////////
     // XXX bugfix for IE11 (lower than IE11 isn't supported for that feature)
     // if a max-height is set on the sheet,
@@ -126,36 +120,68 @@ Tobago.Sheet.setup2 = function (sheets)
     Tobago.Sheet.resetInputFieldSize(jQuery(this));
   });
 
-
   // synchronize column widths
   jQuery(sheets).each(function() {
-    var table = jQuery(this);
 
-    // todo make a function
-    var headerToBody = false;
+    // basic idea: there are two possible sources for the sizes:
+    // 1. the columns attribute of <tc:sheet> like columns="3*;200px;3*", held by data attribute "tobago-layout"
+    // 2. the hidden field which may contain a value like ",300,200,100,"
+    //
+    // The 1st source usually is the default set by the developer.
+    // The 2nd source usually is the value set by the user manipulating the column widths.
+    //
+    // So, if the 2nd is set, we use it, if not set, we use the 1st source.
+    //
+
+    var $sheet = jQuery(this);
+
+    var hidden = Tobago.Sheet.findHiddenWidths($sheet);
+
+    if (hidden.length > 0 && hidden.val()) {
+      // if the hidden has a value, than also the colgroup/col are set correctly
+      var columnWidths = jQuery.parseJSON(hidden.val());
+      console.info("columnWidths: " + columnWidths); // @DEV_ONLY
+      console.info(columnWidths); // @DEV_ONLY
+    } else {
+      // otherwize use the layout definition
+      var layout = $sheet.data("tobago-layout");
+      if (layout && layout.columns && layout.columns.length > 0) {
+        var tokens = layout.columns;
+
+        var $headerTable = $sheet.children("header").children("table");
+        var $headerCol = $headerTable.children("colgroup").children("col");
+        var $bodyTable = $sheet.children("div").children("table");
+        var $bodyCol = $bodyTable.children("colgroup").children("col");
 
-    var body = table.find(".tobago-sheet-bodyTable>colgroup>col");
-    var header = table.find(".tobago-sheet-headerTable>colgroup>col");
+        console.assert(tokens.length == $bodyCol.length, "layout and body column number doesn't match");  // @DEV_ONLY
+        console.assert($headerCol.length == $bodyCol.length, "header and body column number doesn't match");  // @DEV_ONLY
 
-    var sourceCols = headerToBody ? header : body;
-    var targetCols = headerToBody ? body : header;
+        var i;
+        var sumRelative = 0;
+        for (i = 0; i < tokens.length; i++) {
+          if (typeof tokens[i] == "number") {
+            sumRelative += tokens[i];
+          } else {
+            console.warn("not implemented yet: '" + tokens[i] + "'");
+          }
+        }
 
-    console.assert(targetCols.length == sourceCols.length, "header and body column number doesn't match");  // @DEV_ONLY
+        var width = $bodyTable.width();
 
-    for (var i = 0; i < sourceCols.length; i++) {
+        for (i = 0; i < tokens.length; i++) {
+          if (typeof tokens[i] == "number") {
 
-      // if not set, pull the width from a cell (is needed for Chrome)
-      if (sourceCols.eq(i).attr("width") == null) {
-        var correspondingCell
-            = sourceCols.eq(i).parents("table:first").children("tbody").children("tr:first").children("td").eq(i);
-        sourceCols.eq(i).attr("width", correspondingCell.outerWidth())
-      }
+            var colWidth = (tokens[i] * width) / sumRelative;
+            $headerCol.eq(i).attr("width", colWidth);
+            $bodyCol.eq(i).attr("width", colWidth);
+          } else {
+            console.warn("not implemented yet: '" + tokens[i] + "'");
+          }
+        }
 
-      targetCols.eq(i).attr("width", sourceCols.eq(i).attr("width"));
+      }
     }
 
-
-    //COL elemente... // todo
   });
 
   // resize: mouse events
@@ -207,7 +233,7 @@ Tobago.Sheet.setup2 = function (sheets)
         var bodyTable = sheet.find(".tobago-sheet-bodyTable");
         var headerCols = headerTable.find("col");
         var bodyCols = bodyTable.find("col");
-        var widths = ",";
+        var widths = [];
         var oldWidthList = [];
         var i;
         for (i = 0; i < bodyCols.length; i++) {
@@ -218,7 +244,7 @@ Tobago.Sheet.setup2 = function (sheets)
           // last column is the filler column
           var newWidth = headerCols.eq(i).width();
           // for the hidden field
-          widths = widths + newWidth + ",";
+          widths[i] = newWidth;
           usedWidth += newWidth;
 
           var oldWidth = bodyCols.eq(i).width();
@@ -256,12 +282,12 @@ Tobago.Sheet.setup2 = function (sheets)
         }
 
         console.log("SET fillerWidth : " + headerFillerWidth); // @DEV_ONLY
-        widths = widths + headerFillerWidth + ",";
+// TBD filler width seams not to be needed?        widths = widths + headerFillerWidth + ",";
         bodyCols.last().attr("width", bodyFillerWidth);
         headerCols.last().attr("width", headerFillerWidth);
 
         // store the width values in a hidden field
-        Tobago.Sheet.hidden(sheet, "widths").val(widths);
+        Tobago.Sheet.findHiddenWidths(sheet).val(JSON.stringify(widths));
         return false;
       });
     });
@@ -277,14 +303,14 @@ Tobago.Sheet.setup2 = function (sheets)
     sheetBody.siblings(".tobago-sheet-header").prop("scrollLeft", scrollLeft);
 
     // store the position in a hidden field
-    var hidden = Tobago.Sheet.hidden(sheetBody.parent(), "scrollPosition");
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheetBody.parent());
     hidden.val(Math.round(scrollLeft) + ";" + Math.round(scrollTop));
   });
 
   // restore scroll position
   jQuery(sheets).each(function () {
     var sheet = jQuery(this);
-    var hidden = Tobago.Sheet.hidden(sheet, "scrollPosition");
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheet);
     var sep = hidden.val().indexOf(";");
     if (sep != -1) {
       var scrollLeft = hidden.val().substr(0, sep);
@@ -451,14 +477,19 @@ Tobago.Sheet.hideInputOrSubmit = functio
   }
 };
 
-/** Returns the specific hidden field of a sheet
- * @param $sheet The sheet as jQuery Object
- * @param idSuffix The if suffix of the hidden field
- * @return the hidden field.
- * */
-Tobago.Sheet.hidden = function($sheet, idSuffix) {
-  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + idSuffix;
-  return $sheet.children(Tobago.Utils.escapeClientId(id));
+Tobago.Sheet.findHiddenSelected = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "selected";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenScrollPosition = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "scrollPosition";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenWidths = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "widths";
+  return jQuery(Tobago.Utils.escapeClientId(id));
 };
 
 Tobago.Sheet.prototype.setup = function() {
@@ -543,17 +574,17 @@ Tobago.Sheet.isRowSelected = function(sh
 };
 
 Tobago.Sheet.isSelected = function(sheet, rowIndex) {
-  return Tobago.Sheet.hidden(sheet, "selected").val().indexOf("," + rowIndex + ",") >= 0;
+  return Tobago.Sheet.findHiddenSelected(sheet).val().indexOf("," + rowIndex + ",") >= 0;
 };
 
 Tobago.Sheet.resetSelected = function($sheet) {
-  Tobago.Sheet.hidden($sheet, "selected").val(",");
+  Tobago.Sheet.findHiddenSelected($sheet).val(",");
 };
 
 Tobago.Sheet.toggleSelection = function($sheet, $row, $checkbox) {
   $sheet.data("tobago-last-clicked-row-index", $row.index());
   if (!$checkbox.is(":disabled")) {
-    var $selected = Tobago.Sheet.hidden($sheet, "selected");
+    var $selected = Tobago.Sheet.findHiddenSelected($sheet);
     var rowIndex = Tobago.Sheet.getDataIndex($sheet, $row);
     if (Tobago.Sheet.isSelected($sheet, rowIndex)) {
       Tobago.Sheet.deselectRow($selected, rowIndex, $row, $checkbox);
@@ -582,7 +613,7 @@ Tobago.Sheet.selectRange = function($she
   if ($rows.size() == 0) {
     return;
   }
-  var selected = Tobago.Sheet.hidden($sheet, "selected");
+  var selected = Tobago.Sheet.findHiddenSelected($sheet);
   for (var i = first; i <= last; i++) {
     var row = $rows.eq(i);
     var checkbox = Tobago.Sheet.getSelectorCheckbox(row);

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/style/tobago.css
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/style/tobago.css?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/style/tobago.css (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/style/tobago.css Thu Apr  7 08:12:11 2016
@@ -421,10 +421,9 @@ h6 > .fa:first-child {
   cursor: pointer;
 }
 
-table.tobago-sheet-headerTable>tbody>tr>th:last-child,
-table.tobago-sheet-bodyTable>tbody>tr>td:last-child {
-  padding-left: 0;
-  padding-right: 0;
+table.tobago-sheet-headerTable>tbody>tr>th,
+table.tobago-sheet-bodyTable>tbody>tr>td {
+  padding: 0;
 }
 
 .tobago-sheet-body {
@@ -436,71 +435,22 @@ table.tobago-sheet-bodyTable>tbody>tr>td
   margin-bottom: 0;
 }
 
-table.tobago-sheet-fixHeader > thead,
-table.tobago-sheet-fixHeader > tbody,
-table.tobago-sheet-fixHeader > thead > tr,
-table.tobago-sheet-fixHeader > tbody > tr,
-table.tobago-sheet-fixHeader > thead > tr > th,
-table.tobago-sheet-fixHeader > tbody > tr > td {
-  display: block;
+.tableLayout-fixed {
+  table-layout: fixed;
 }
 
-table.tobago-sheet-fixHeader > thead > tr:after,
-table.tobago-sheet-fixHeader > tbody > tr:after {
-  content: ' ';
-  display: block;
-  visibility: hidden;
-  clear: both;
+.tobago-sheet-headerCell {
+  position: relative;
 }
 
-table.tobago-sheet-fixHeader > thead > tr > th {
-  /*height: 30px;*/
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th {
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-table.tobago-sheet-fixHeader > tbody {
-  height: 300px;
-  overflow-y: auto;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th,
-table.tobago-sheet-fixHeader > tbody > tr > td {
-  float: left;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th,
-table.tobago-sheet-fixHeader > tbody > tr > td {
-  width: 10%;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th:nth-child(1),
-table.tobago-sheet-fixHeader > tbody > tr > td:nth-child(1) {
-  width: 20%;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th:nth-child(2),
-table.tobago-sheet-fixHeader > tbody > tr > td:nth-child(2) {
-  width: 20%;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th:nth-child(3),
-table.tobago-sheet-fixHeader > tbody > tr > td:nth-child(3) {
-  width: 20%;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th:nth-child(4),
-table.tobago-sheet-fixHeader > tbody > tr > td:nth-child(4) {
-  width: 20%;
-}
-
-table.tobago-sheet-fixHeader > thead > tr > th.tobago-sheet-selectorDropdown {
-  /* This is to override the rule above, and the drowdown would be clipped. */
-  overflow: visible;
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
 }
 
 /* suggest ---------------------------------------------------------------------- */

Modified: myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/JsonUtilsUnitTest.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/JsonUtilsUnitTest.java?rev=1738103&r1=1738102&r2=1738103&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/JsonUtilsUnitTest.java (original)
+++ myfaces/tobago/branches/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/JsonUtilsUnitTest.java Thu Apr  7 08:12:11 2016
@@ -129,4 +129,22 @@ public class JsonUtilsUnitTest extends A
     Assert.assertEquals(expected, JsonUtils.encode(dateTimeI18n));
   }
 
+  @Test
+  public void decodeIntegerArray() {
+
+    Assert.assertEquals(Arrays.asList(1,2,3,4), JsonUtils.decodeIntegerArray("[1,2,3,4]"));
+
+    Assert.assertEquals(Arrays.asList(1,2,3,4), JsonUtils.decodeIntegerArray(" [ 1 , 2 , 3 , 4 ] "));
+
+    Assert.assertEquals(Arrays.asList(1), JsonUtils.decodeIntegerArray("[1]"));
+
+    Assert.assertEquals(Arrays.asList(), JsonUtils.decodeIntegerArray("[]"));
+
+    Assert.assertEquals(Arrays.asList(1000000000,2,3,4), JsonUtils.decodeIntegerArray("[1000000000,2,3,4]"));
+
+    Assert.assertEquals(Arrays.asList(2,3,4), JsonUtils.decodeIntegerArray("[null,2,3,4]"));
+
+    Assert.assertEquals(null, JsonUtils.decodeIntegerArray("1,2,3,4"));
+  }
+
 }