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 2017/11/01 12:35:35 UTC

[myfaces-tobago] branch master updated: TOBAGO-1818: Progress in the Measure class (cleanup and CSS support) # The LayoutToken and Measure classes are quite similar and should be consolidated. # As a result, we should add a MeasureList to manage a list of Measures. This list should be the type of the corresponding layout manager attributes. # The syntax should also cover the CSS wording like * "auto" * "3*" should be written as "3fr" (fraction) * SegmentLayout should be also use "3seg" instead of "3".

This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/master by this push:
     new 5dc17ee  TOBAGO-1818: Progress in the Measure class (cleanup and CSS support) # The LayoutToken and Measure classes are quite similar and should be consolidated. # As a result, we should add a MeasureList to manage a list of Measures. This list should be the type of the corresponding layout manager attributes. # The syntax should also cover the CSS wording like   * "auto"   * "3*" should be written as "3fr" (fraction)   * SegmentLayout should be also use "3seg" instead of "3".
5dc17ee is described below

commit 5dc17eebb2b213af91b0124ee77bb1b225a03d5a
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Wed Nov 1 13:35:22 2017 +0100

    TOBAGO-1818: Progress in the Measure class (cleanup and CSS support)
    # The LayoutToken and Measure classes are quite similar and should be consolidated.
    # As a result, we should add a MeasureList to manage a list of Measures. This list should be the type of the corresponding layout manager attributes.
    # The syntax should also cover the CSS wording like
      * "auto"
      * "3*" should be written as "3fr" (fraction)
      * SegmentLayout should be also use "3seg" instead of "3".
---
 .../myfaces/tobago/component/Attributes.java       |   1 +
 .../internal/component/AbstractUIFlexLayout.java   |  66 ++++----
 .../internal/component/AbstractUIGridLayout.java   |   8 +-
 .../component/AbstractUISegmentLayout.java         |  11 +-
 .../tobago/internal/component/AbstractUISheet.java |  37 ++---
 .../tobago/internal/component/AbstractUIStyle.java |   9 +-
 .../myfaces/tobago/internal/layout/BankHead.java   |  59 -------
 .../myfaces/tobago/internal/layout/Grid.java       |  16 +-
 .../renderkit/renderer/GridLayoutRenderer.java     |  10 +-
 .../renderkit/renderer/SegmentLayoutRenderer.java  |  11 +-
 .../internal/renderkit/renderer/StyleRenderer.java |   8 +-
 .../taglib/component/FlexLayoutTagDeclaration.java |   4 +-
 .../taglib/component/GridLayoutTagDeclaration.java |   9 --
 .../component/SegmentLayoutTagDeclaration.java     |  10 +-
 .../component/SplitLayoutTagDeclaration.java       |  24 +--
 .../taglib/component/StyleTagDeclaration.java      |   4 +-
 .../myfaces/tobago/internal/util/JsonUtils.java    |  28 ++--
 .../apache/myfaces/tobago/layout/LayoutToken.java  |  23 ---
 .../apache/myfaces/tobago/layout/LayoutTokens.java | 175 ---------------------
 .../org/apache/myfaces/tobago/layout/Measure.java  | 112 ++++++++-----
 .../myfaces/tobago/layout/MeasureLayoutToken.java  |  66 --------
 .../apache/myfaces/tobago/layout/MeasureList.java  |  74 +++++++++
 ...AutoLayoutToken.java => MeasureListEditor.java} |  23 ++-
 .../myfaces/tobago/layout/RelativeLayoutToken.java |  63 --------
 .../myfaces/tobago/layout/SegmentLayoutToken.java  |  64 --------
 ...ideLayoutToken.java => SegmentMeasureList.java} |  20 ++-
 ...outToken.java => SegmentMeasureListEditor.java} |  24 ++-
 .../tobago/renderkit/css/BootstrapClass.java       |  51 +++---
 .../tobago/internal/layout/GridUnitTest.java       |   8 +-
 .../tobago/layout/LayoutTokensUnitTest.java        |  56 -------
 .../myfaces/tobago/layout/MeasureUnitTest.java     |   6 +
 .../16-layout/60-split/split-layout.xhtml          |  22 ++-
 .../org/apache/myfaces/tobago/apt/component.stg    |  12 ++
 33 files changed, 371 insertions(+), 743 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
index 654803b..6d9e245 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
@@ -310,6 +310,7 @@ public enum Attributes {
   required,
   resizable,
   right,
+  @Deprecated
   rigid,
   rowId,
   @Deprecated
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java
index 45a4f46..08e075e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java
@@ -22,11 +22,9 @@ package org.apache.myfaces.tobago.internal.component;
 import org.apache.myfaces.tobago.component.RendererTypes;
 import org.apache.myfaces.tobago.component.UIStyle;
 import org.apache.myfaces.tobago.component.Visual;
-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.layout.MeasureList;
+import org.apache.myfaces.tobago.util.ComponentUtils;
 
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
@@ -52,47 +50,43 @@ public abstract class AbstractUIFlexLayout extends AbstractUILayoutBase implemen
 
       final boolean horizontal = isHorizontal();
 
-      String tokensString = getColumns();
-      if (tokensString == null) {
-        tokensString = getRows();
-        if (tokensString == null) {
-          tokensString = "auto"; // XXX magic string
-        }
+      MeasureList tokens = horizontal ? getColumns() : getRows();
+      if (tokens == null) {
+        tokens = new MeasureList();
+        tokens.add(Measure.AUTO);
       }
-      final LayoutTokens tokens = LayoutTokens.parse(tokensString);
+
       if (tokens.getSize() > 0) {
         int i = 0;
 
         for (UIComponent child : getChildren()) {
           if (child instanceof Visual) {
-            final Visual visual = (Visual) child;
             if (i >= tokens.getSize()) {
               i = 0;
             }
-            final LayoutToken token = tokens.get(i++);
-            if (token instanceof MeasureLayoutToken) {
-              final Measure measure = ((MeasureLayoutToken) token).getMeasure();
-              // XXX only create if there is no child UIStyle
-              UIStyle style = (UIStyle) facesContext.getApplication().createComponent(
-                  facesContext, UIStyle.COMPONENT_TYPE, RendererTypes.Style.name());
-              style.setTransient(true);
-              if (horizontal) {
-                style.setWidth(measure);
+            final Measure token = tokens.get(i++);
+            final Measure.Unit unit = token.getUnit();
+            if (unit != Measure.Unit.AUTO) {
+              AbstractUIStyle style = ComponentUtils.findChild(child, AbstractUIStyle.class);
+              if (style == null) {
+                style = (AbstractUIStyle) facesContext.getApplication().createComponent(
+                    facesContext, UIStyle.COMPONENT_TYPE, RendererTypes.Style.name());
+                style.setTransient(true);
+                child.getChildren().add(style);
+              }
+              if (unit == Measure.Unit.FR) {
+                final float factor = token.getValue();
+                style.setFlexGrow(factor);
+                style.setFlexShrink(0);
+                style.setFlexBasis(Measure.ZERO);
+//                style.setFlexBasis(Measure.AUTO); // is unbalanced when mixing e.g. <p> with <textarea>
               } else {
-                style.setHeight(measure);
+                if (horizontal) {
+                  style.setWidth(token);
+                } else {
+                  style.setHeight(token);
+                }
               }
-              ((UIComponent) visual).getChildren().add(style);
-            } else if (token instanceof RelativeLayoutToken) {
-              final int factor = ((RelativeLayoutToken) token).getFactor();
-              // XXX only create if there is no child UIStyle
-              UIStyle style = (UIStyle) facesContext.getApplication().createComponent(
-                  facesContext, UIStyle.COMPONENT_TYPE, RendererTypes.Style.name());
-              style.setTransient(true);
-              style.setFlexGrow(factor);
-              style.setFlexShrink(0);
-              style.setFlexBasis(Measure.ZERO);
-// todo             style.setFlexBasis("auto");
-              ((UIComponent) visual).getChildren().add(style);
             }
           }
         }
@@ -100,9 +94,9 @@ public abstract class AbstractUIFlexLayout extends AbstractUILayoutBase implemen
     }
   }
 
-  public abstract java.lang.String getColumns();
+  public abstract MeasureList getColumns();
 
-  public abstract java.lang.String getRows();
+  public abstract MeasureList getRows();
 
   public boolean isHorizontal() {
     return getRows() == null;
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java
index 5d187cd..2797b6d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java
@@ -27,7 +27,7 @@ import org.apache.myfaces.tobago.component.UIStyle;
 import org.apache.myfaces.tobago.component.Visual;
 import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
 import org.apache.myfaces.tobago.layout.GridSpan;
-import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -76,8 +76,8 @@ public abstract class AbstractUIGridLayout extends AbstractUILayoutBase
     if (event instanceof PreRenderComponentEvent) {
 
       layout(
-          LayoutTokens.parse(getColumns()).getSize(),
-          LayoutTokens.parse(getRows()).getSize(),
+          MeasureList.parse(getColumns()).getSize(),
+          MeasureList.parse(getRows()).getSize(),
           LayoutUtils.findLayoutChildren(this));
 
     }
@@ -91,8 +91,6 @@ public abstract class AbstractUIGridLayout extends AbstractUILayoutBase
 
   public abstract void setColumns(String columns);
 
-  public abstract boolean isRigid();
-
   protected UIComponent[][] layout(
       final int columnsCount, final int initalRowsCount, final List<UIComponent> components) {
     assert columnsCount > 0;
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java
index e2daf32..cd94625 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java
@@ -20,6 +20,7 @@
 package org.apache.myfaces.tobago.internal.component;
 
 import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.layout.MeasureList;
 
 /**
  * {@link org.apache.myfaces.tobago.internal.taglib.component.SegmentLayoutTagDeclaration}
@@ -56,13 +57,13 @@ public abstract class AbstractUISegmentLayout extends AbstractUILayoutBase imple
     return builder.toString();
   }
 
-  public abstract String getExtraSmall();
+  public abstract MeasureList getExtraSmall();
 
-  public abstract String getSmall();
+  public abstract MeasureList getSmall();
 
-  public abstract String getMedium();
+  public abstract MeasureList getMedium();
 
-  public abstract String getLarge();
+  public abstract MeasureList getLarge();
 
-  public abstract String getExtraLarge();
+  public abstract MeasureList getExtraLarge();
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
index 44efe4a..e4d87cf 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
@@ -30,10 +30,8 @@ import org.apache.myfaces.tobago.event.SortActionEvent;
 import org.apache.myfaces.tobago.event.SortActionSource2;
 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.layout.Measure;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.apache.myfaces.tobago.model.ExpandedState;
 import org.apache.myfaces.tobago.model.SelectedState;
 import org.apache.myfaces.tobago.model.SheetState;
@@ -67,7 +65,7 @@ import java.util.List;
 @ListenerFor(systemEventClass = PreRenderComponentEvent.class)
 public abstract class AbstractUISheet extends AbstractUIData
     implements SheetStateChangeSource2, SortActionSource2, ClientBehaviorHolder, Visual,
-               ComponentSystemEventListener {
+    ComponentSystemEventListener {
 
   private static final Logger LOG = LoggerFactory.getLogger(AbstractUISheet.class);
 
@@ -76,7 +74,7 @@ public abstract class AbstractUISheet extends AbstractUIData
   public static final String SORTER_ID = "sorter";
 
   private SheetState state;
-  private transient LayoutTokens columnLayout;
+  private transient MeasureList columnLayout;
   private transient boolean autoLayout;
 
   private transient Grid headerGrid;
@@ -135,13 +133,13 @@ public abstract class AbstractUISheet extends AbstractUIData
     if (event instanceof PreRenderComponentEvent) {
       final String columns = getColumns();
       if (columns != null) {
-        columnLayout = LayoutTokens.parse(columns);
+        columnLayout = MeasureList.parse(columns);
       }
 
       autoLayout = true;
       if (columnLayout != null) {
-        for (LayoutToken layoutToken : columnLayout.getTokens()) {
-          if (!(layoutToken instanceof AutoLayoutToken)) {
+        for (Measure token : columnLayout) {
+          if (token != Measure.AUTO) {
             autoLayout = false;
             break;
           }
@@ -152,7 +150,7 @@ public abstract class AbstractUISheet extends AbstractUIData
     }
   }
 
-  public LayoutTokens getColumnLayout() {
+  public MeasureList getColumnLayout() {
     return columnLayout;
   }
 
@@ -171,8 +169,9 @@ public abstract class AbstractUISheet extends AbstractUIData
 
   /**
    * The rowIndex of the last row on the current page plus one (because of zero based iterating).
+   *
    * @throws IllegalArgumentException If the number of rows in the model returned
-   * by {@link #getRowCount()} is -1 (undefined).
+   *                                  by {@link #getRowCount()} is -1 (undefined).
    */
   public int getLastRowIndexOfCurrentPage() {
     if (!hasRowCount()) {
@@ -202,7 +201,7 @@ public abstract class AbstractUISheet extends AbstractUIData
       return first / rows;
     }
   }
-  
+
   /**
    * @return returns the current page (based by 1).
    * @deprecated Please use {@link #getCurrentPage()} which returns the value zero-based. Deprecated since 1.5.5.
@@ -214,8 +213,9 @@ public abstract class AbstractUISheet extends AbstractUIData
 
   /**
    * The number of pages to render.
+   *
    * @throws IllegalArgumentException If the number of rows in the model returned
-   * by {@link #getRowCount()} is -1 (undefined).
+   *                                  by {@link #getRowCount()} is -1 (undefined).
    */
   public int getPages() {
     if (isRowsUnlimited()) {
@@ -290,9 +290,10 @@ public abstract class AbstractUISheet extends AbstractUIData
   /**
    * Determines the beginning of the last page in the model.
    * If the number of rows to display on one page is unlimited, the value is 0 (there is only one page).
+   *
    * @return The index of the first row of the last paging page.
    * @throws IllegalArgumentException If the number of rows in the model returned
-   * by {@link #getRowCount()} is -1 (undefined).
+   *                                  by {@link #getRowCount()} is -1 (undefined).
    */
   public int getFirstRowIndexOfLastPage() {
     if (isRowsUnlimited()) {
@@ -404,15 +405,15 @@ public abstract class AbstractUISheet extends AbstractUIData
       LOG.warn("This should not happen. Please file a bug in the issue tracker to reproduce this case.");
       return;
     }
-    final LayoutTokens tokens = new LayoutTokens();
+    final MeasureList tokens = new MeasureList();
     final List<AbstractUIColumnBase> columns = getAllColumns();
     for (final UIColumn column : columns) {
       if (!(column instanceof AbstractUIRow)) {
-        tokens.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
+        tokens.add(Measure.FRACTION1);
       }
     }
-    final LayoutTokens rows = new LayoutTokens();
-    rows.addToken(AutoLayoutToken.INSTANCE);
+    final MeasureList rows = new MeasureList();
+    rows.add(Measure.AUTO);
     final Grid grid = new Grid(tokens, rows);
 
     for (final UIComponent child : header.getChildren()) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIStyle.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIStyle.java
index 44acf50..ea7d99a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIStyle.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIStyle.java
@@ -106,6 +106,7 @@ public abstract class AbstractUIStyle extends UIComponentBase {
   public abstract Measure getPaddingTop();
 
   public abstract Measure getHeight();
+  public abstract void setHeight(Measure height);
 
   public abstract Measure getMaxWidth();
 
@@ -128,6 +129,7 @@ public abstract class AbstractUIStyle extends UIComponentBase {
   public abstract Measure getLeft();
 
   public abstract Measure getWidth();
+  public abstract void setWidth(Measure width);
 
   public abstract CustomClass getCustomClass();
 
@@ -141,11 +143,14 @@ public abstract class AbstractUIStyle extends UIComponentBase {
 
   public abstract String getBackgroundImage();
 
-  public abstract Integer getFlexGrow();
+  public abstract Number getFlexGrow();
+  public abstract void setFlexGrow(Number flexGrow);
 
-  public abstract Integer getFlexShrink();
+  public abstract Number getFlexShrink();
+  public abstract void setFlexShrink(Number flexShrink);
 
   public abstract Measure getFlexBasis();
+  public abstract void setFlexBasis(Measure flexBasis);
 
   public abstract String getGridTemplateColumns();
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java
deleted file mode 100644
index 1cf37d6..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.internal.layout;
-
-import org.apache.myfaces.tobago.layout.LayoutToken;
-
-/**
- * BankHead represents the head information of a bank like the token for this bank, the computed
- * "current" and "minimum" measure and if it will be rendered. A bank is a generalization for columns and rows.
- */
-public class BankHead {
-
-  private LayoutToken token;
-
-  private boolean rendered;
-
-  public BankHead(final LayoutToken token) {
-    this.token = token;
-    this.rendered = true;
-  }
-
-  public LayoutToken getToken() {
-    return token;
-  }
-
-  public void setToken(final LayoutToken token) {
-    this.token = token;
-  }
-
-  public boolean isRendered() {
-    return rendered;
-  }
-
-  public void setRendered(final boolean rendered) {
-    this.rendered = rendered;
-  }
-
-  @Override
-  public String toString() {
-    return "BankHead{" + token + "," + rendered + '}';
-  }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java
index 5ce7c56..bdc12b0 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java
@@ -19,8 +19,8 @@
 
 package org.apache.myfaces.tobago.internal.layout;
 
-import org.apache.myfaces.tobago.layout.LayoutTokens;
-import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,8 +41,8 @@ public class Grid {
    */
   private List<Cell> cells;
 
-  private LayoutTokens columns;
-  private LayoutTokens rows;
+  private MeasureList columns;
+  private MeasureList rows;
 
   private int columnCount;
   private int rowCount;
@@ -52,7 +52,7 @@ public class Grid {
 
   private List<Integer> errorIndexes;
 
-  public Grid(final LayoutTokens columns, final LayoutTokens rows) {
+  public Grid(final MeasureList columns, final MeasureList rows) {
     assert columns.getSize() > 0;
     assert rows.getSize() > 0;
 
@@ -144,11 +144,11 @@ public class Grid {
     }
   }
 
-  public LayoutTokens getColumns() {
+  protected MeasureList getColumns() {
     return columns;
   }
 
-  public LayoutTokens getRows() {
+  protected MeasureList getRows() {
     return rows;
   }
 
@@ -163,7 +163,7 @@ public class Grid {
 
     // process heads
     for (int i = rowCount; i < rowCount + newRows; i++) {
-      rows.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
+      rows.add(Measure.FRACTION1);
     }
 
     rowCount += newRows;
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java
index 42dff36..1888159 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java
@@ -22,7 +22,7 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.component.RendererTypes;
 import org.apache.myfaces.tobago.component.UIStyle;
 import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
-import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
@@ -50,15 +50,15 @@ public class GridLayoutRenderer extends RendererBase {
     writer.writeIdAttribute(gridLayout.getClientId(facesContext));
     writer.writeClassAttribute(TobagoClass.GRID_LAYOUT);
 
-    final LayoutTokens columns = LayoutTokens.parse(gridLayout.getColumns());
-    final LayoutTokens rows = LayoutTokens.parse(gridLayout.getRows());
+    final MeasureList columns = MeasureList.parse(gridLayout.getColumns());
+    final MeasureList rows = MeasureList.parse(gridLayout.getRows());
 
     final UIStyle style = (UIStyle) facesContext.getApplication().createComponent(
         facesContext, UIStyle.COMPONENT_TYPE, RendererTypes.Style.name());
     style.setTransient(true);
 
-    style.setGridTemplateColumns(columns.encodeToGrid());
-    style.setGridTemplateRows(rows.encodeToGrid());
+    style.setGridTemplateColumns(columns.serialize());
+    style.setGridTemplateRows(rows.serialize());
     gridLayout.getChildren().add(style);
   }
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java
index ad49997..d9e011e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java
@@ -23,7 +23,6 @@ import org.apache.myfaces.tobago.component.LabelLayout;
 import org.apache.myfaces.tobago.component.SupportsLabelLayout;
 import org.apache.myfaces.tobago.component.UISegmentLayout;
 import org.apache.myfaces.tobago.internal.component.AbstractUISegmentLayout;
-import org.apache.myfaces.tobago.layout.LayoutTokens;
 import org.apache.myfaces.tobago.layout.MarginTokens;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -77,11 +76,11 @@ public class SegmentLayoutRenderer extends RendererBase {
 
     final List<UIComponent> children = segmentLayout.getChildren();
     final BootstrapClass.Generator generator = new BootstrapClass.Generator(
-        LayoutTokens.parse(segmentLayout.getExtraSmall()),
-        LayoutTokens.parse(segmentLayout.getSmall()),
-        LayoutTokens.parse(segmentLayout.getMedium()),
-        LayoutTokens.parse(segmentLayout.getLarge()),
-        LayoutTokens.parse(segmentLayout.getExtraLarge()),
+        segmentLayout.getExtraSmall(),
+        segmentLayout.getSmall(),
+        segmentLayout.getMedium(),
+        segmentLayout.getLarge(),
+        segmentLayout.getExtraLarge(),
         MarginTokens.parse(segmentLayout.getMarginExtraSmall()),
         MarginTokens.parse(segmentLayout.getMarginSmall()),
         MarginTokens.parse(segmentLayout.getMarginMedium()),
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java
index fa0a63c..a1cff0c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java
@@ -87,8 +87,8 @@ public class StyleRenderer extends RendererBase {
       final Position position = style.getPosition();
       final TextAlign textAlign = style.getTextAlign();
       final String backgroundImage = style.getBackgroundImage();
-      final Integer flexGrow = style.getFlexGrow();
-      final Integer flexShrink = style.getFlexShrink();
+      final Number flexGrow = style.getFlexGrow();
+      final Number flexShrink = style.getFlexShrink();
       final Measure flexBasis = style.getFlexBasis();
       final String gridTemplateColumns = style.getGridTemplateColumns();
       final String gridTemplateRows = style.getGridTemplateRows();
@@ -213,10 +213,10 @@ public class StyleRenderer extends RendererBase {
           encodeStyle(writer, Styles.backgroundImage, backgroundImage);
         }
         if (flexGrow != null) {
-          encodeStyle(writer, Styles.flexGrow, Integer.toString(flexGrow));
+          encodeStyle(writer, Styles.flexGrow, String.valueOf(flexGrow));
         }
         if (flexShrink != null) {
-          encodeStyle(writer, Styles.flexShrink, Integer.toString(flexShrink));
+          encodeStyle(writer, Styles.flexShrink, String.valueOf(flexShrink));
         }
         if (flexBasis != null) {
           encodeStyle(writer, Styles.flexBasis, flexBasis.serialize());
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java
index 5050463..494e321 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java
@@ -55,7 +55,7 @@ public interface FlexLayoutTagDeclaration extends HasIdBindingAndRendered, IsVis
    * Example: '2*;*;100px;3rem;auto'.
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.MeasureList")
   void setColumns(String columns);
 
   /**
@@ -65,7 +65,7 @@ public interface FlexLayoutTagDeclaration extends HasIdBindingAndRendered, IsVis
    * Example: '2*;*;100px;3rem;auto'.
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.MeasureList")
   void setRows(String rows);
 
   /**
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java
index b63021a..09883dc 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java
@@ -21,9 +21,7 @@ package org.apache.myfaces.tobago.internal.taglib.component;
 
 import org.apache.myfaces.tobago.apt.annotation.Preliminary;
 import org.apache.myfaces.tobago.apt.annotation.Tag;
-import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
 import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
-import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
 import org.apache.myfaces.tobago.component.RendererTypes;
 import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
 import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
@@ -109,11 +107,4 @@ import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
 public interface GridLayoutTagDeclaration extends HasId, HasSpacing,
     HasColumnLayout, HasRowLayout, HasBinding, IsVisual {
 
-  /**
-   * This attribute advises the layout manager, to not use space that comes from non rendered components.
-   */
-  @TagAttribute
-  @UIComponentTagAttribute(type = "boolean")
-  void setRigid(String rigid);
-
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java
index ecc8f21..9027dca 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java
@@ -54,7 +54,7 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
    * Example: '1;5;*;auto'
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.SegmentMeasureList")
   void setExtraSmall(String extraSmall);
 
   /**
@@ -63,7 +63,7 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
    * Example: '1;5;*;auto'
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.SegmentMeasureList")
   void setSmall(String small);
 
   /**
@@ -72,7 +72,7 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
    * Example: '1;5;*;auto'
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.SegmentMeasureList")
   void setMedium(String medium);
 
   /**
@@ -81,7 +81,7 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
    * Example: '1;5;*;auto'
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.SegmentMeasureList")
   void setLarge(String large);
 
   /**
@@ -90,7 +90,7 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
    * Example: '1;5;*;auto'
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.SegmentMeasureList")
   void setExtraLarge(String extraLarge);
 
   /**
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SplitLayoutTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SplitLayoutTagDeclaration.java
index f0ec739..6a9f748 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SplitLayoutTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SplitLayoutTagDeclaration.java
@@ -51,24 +51,13 @@ public interface SplitLayoutTagDeclaration
       extends HasId, HasSpacing, HasBinding, IsVisual {
 
   /**
-   * This value defines the layout constraints for the layout.
-   * It is two layout tokens separated by a semicolon.
-   * Example: '2*;*'.
-   */
-/*
-  @TagAttribute
-  @UIComponentTagAttribute(defaultValue = "1*;1*")
-  void setLayout(String rows);
-*/
-
-  /**
    * This value defines the layout constraints for column layout.
    * It is a semicolon separated list of layout tokens '&lt;n&gt;*', '&lt;measure&gt;' or the keyword 'auto'.
    * Where &lt;n&gt; is a positive integer or empty and &lt;measure&gt; is a valid CSS length.
    * Example: '2*;*;100px;3rem;auto'.
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.MeasureList")
   void setColumns(String columns);
 
   /**
@@ -78,15 +67,6 @@ public interface SplitLayoutTagDeclaration
    * Example: '2*;*;100px;3rem;auto'.
    */
   @TagAttribute
-  @UIComponentTagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.MeasureList")
   void setRows(String rows);
-
-  /**
-   * This attribute advises the layout manager, to not use space that comes from non rendered components.
-   */
-/* tbd
-  @TagAttribute
-  @UIComponentTagAttribute(type = "boolean")
-  void setRigid(String rigid);
-*/
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java
index 3c71ec2..b06541d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java
@@ -291,7 +291,7 @@ public interface StyleTagDeclaration extends HasIdBindingAndRendered {
    * @since 4.0.0
    */
   @TagAttribute
-  @UIComponentTagAttribute(type = "java.lang.Integer")
+  @UIComponentTagAttribute(type = "java.lang.Number")
   void setFlexGrow(String flexGrow);
 
   /**
@@ -300,7 +300,7 @@ public interface StyleTagDeclaration extends HasIdBindingAndRendered {
    * @since 4.0.0
    */
   @TagAttribute
-  @UIComponentTagAttribute(type = "java.lang.Integer")
+  @UIComponentTagAttribute(type = "java.lang.Number")
   void setFlexShrink(String flexShrink);
 
   /**
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java
index 2f71fca..11d9a8e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java
@@ -24,11 +24,8 @@ import org.apache.myfaces.tobago.internal.context.DateTimeI18n;
 import org.apache.myfaces.tobago.internal.renderkit.Collapse;
 import org.apache.myfaces.tobago.internal.renderkit.Command;
 import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
-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.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -121,7 +118,7 @@ public class JsonUtils {
 
     final Map<ClientBehaviors, Command> other = commandMap.getOther();
     if (other != null) {
-      for(final Map.Entry<ClientBehaviors, Command> entry : other.entrySet()) {
+      for (final Map.Entry<ClientBehaviors, Command> entry : other.entrySet()) {
         encode(builder, entry.getKey(), entry.getValue());
       }
     }
@@ -173,7 +170,7 @@ public class JsonUtils {
     if (confirmation != null) {
       encode(builder, "confirmation", confirmation);
     }
-    final Integer delay  = command.getDelay();
+    final Integer delay = command.getDelay();
     if (delay != null) {
       encode(builder, "delay", delay);
     }
@@ -250,20 +247,19 @@ public class JsonUtils {
     return builder.toString();
   }
 
-  public static void encode(final LayoutTokens bankHeads, final StringBuilder builder) {
+  public static void encode(final MeasureList layout, final StringBuilder builder) {
     builder.append("[");
-    for (final LayoutToken token : bankHeads.getTokens()) {
-      if (token instanceof RelativeLayoutToken) {
-        final int factor = ((RelativeLayoutToken) token).getFactor();
+    for (final Measure measure : layout) {
+      final Measure.Unit unit = measure.getUnit();
+      if (unit == Measure.Unit.FR) {
+        final float factor = measure.getValue(); // todo: might be better with "fr" suffix, but needs a JS change
         builder.append(factor);
-      } else if (token instanceof AutoLayoutToken) {
+      } else if (unit == Measure.Unit.AUTO) {
         builder.append("\"auto\"");
-      } else if (token instanceof MeasureLayoutToken) {
+      } else {
         builder.append("{\"measure\":\"");
-        builder.append(((MeasureLayoutToken) token).getMeasure());
+        builder.append(measure.serialize());
         builder.append("\"}");
-      } else {
-        LOG.warn("Not supported: " + token);
       }
       builder.append(',');
     }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java
deleted file mode 100644
index 67f412f..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-public class LayoutToken {
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java
deleted file mode 100644
index 697ec63..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-import org.apache.myfaces.tobago.internal.util.NumberUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-
-public final class LayoutTokens implements Iterable<LayoutToken> {
-
-  private static final Logger LOG = LoggerFactory.getLogger(LayoutTokens.class);
-
-  private List<LayoutToken> tokens = new ArrayList<>();
-
-  public LayoutTokens() {
-  }
-
-  public int getSize() {
-    return tokens.size();
-  }
-
-  public void set(final int index, final LayoutToken token) {
-    tokens.set(index, token);
-  }
-
-  public boolean isEmpty() {
-    return getSize() == 0;
-  }
-
-  public LayoutToken get(final int index) {
-    return tokens.get(index);
-  }
-
-  public void addToken(final LayoutToken token) {
-    tokens.add(token);
-  }
-
-  public List<LayoutToken> getTokens() {
-    return tokens;
-  }
-
-  @Override
-  public Iterator<LayoutToken> iterator() {
-    return tokens.iterator();
-  }
-
-  public static LayoutTokens parse(final String[] tokens) {
-    final LayoutTokens layoutTokens = new LayoutTokens();
-    for (final String token : tokens) {
-      parseToken(token, layoutTokens);
-    }
-    return layoutTokens;
-  }
-
-  public static LayoutTokens parse(final String tokens) {
-    return parse(tokens, null);
-  }
-
-  public static LayoutTokens parse(final String tokens, final LayoutToken defaultToken) {
-    final LayoutTokens layoutTokens = new LayoutTokens();
-    if (tokens == null) {
-      layoutTokens.addToken(defaultToken);
-      return layoutTokens;
-    }
-    final StringTokenizer tokenizer = new StringTokenizer(tokens, ";");
-
-    while (tokenizer.hasMoreTokens()) {
-      final String token = tokenizer.nextToken().trim();
-      parseToken(token, layoutTokens);
-    }
-    return layoutTokens;
-  }
-
-  private static void parseToken(final String token, final LayoutTokens layoutTokens) {
-    final LayoutToken layoutToken = parseToken(token);
-    if (layoutToken != null) {
-      layoutTokens.addToken(layoutToken);
-    }
-  }
-
-  public static LayoutToken parseToken(final String token) {
-    try {
-      if ("*".equals(token)) {
-        return RelativeLayoutToken.DEFAULT_INSTANCE;
-      } else if (token == null) {
-        LOG.error("Empty layout token! Using 'auto' instead.");
-        return AutoLayoutToken.INSTANCE;
-      } else if ("fixed".equals(token) || "auto".equals(token)) {
-        return AutoLayoutToken.INSTANCE;
-      } else if ("minimum".equals(token)) {
-        return new MinimumLayoutToken();
-      } else if (isRelativeToken(token)) {
-        return new RelativeLayoutToken(Integer.parseInt(removeSuffix(token, RelativeLayoutToken.SUFFIX)));
-      } else if (isSegmentLayoutToken(token)) {
-        return new SegmentLayoutToken(Integer.parseInt(token));
-      } else {
-        return new MeasureLayoutToken(token);
-      }
-    } catch (final NumberFormatException e) {
-      LOG.error("Error parsing layout token '" + token + "'! Using 'auto' instead.");
-      return AutoLayoutToken.INSTANCE;
-    }
-  }
-
-  static boolean isRelativeToken(final String token) {
-    return isNumberAndSuffix(token, RelativeLayoutToken.SUFFIX);
-  }
-
-  static boolean isNumberAndSuffix(final String token, final String suffix) {
-    return token.endsWith(suffix) && NumberUtils.isDigits(removeSuffix(token, suffix));
-  }
-
-  static boolean isSegmentLayoutToken(final String token) {
-    return NumberUtils.isDigits(token);
-  }
-
-  private static String removeSuffix(final String token, final String suffix) {
-    return token.substring(0, token.length() - suffix.length());
-  }
-
-  // XXX todo: refactor/cleanup
-  public String encodeToGrid() {
-    final StringBuilder builder = new StringBuilder();
-    for (LayoutToken token : tokens) {
-      if (token instanceof RelativeLayoutToken) {
-        builder
-            .append(((RelativeLayoutToken) token).getFactor())
-            .append("fr")
-            .append(' ');
-      } else {
-        builder
-            .append(token.toString())
-            .append(' ');
-      }
-    }
-    if (builder.length() > 0) {
-      builder.deleteCharAt(builder.length() - 1);
-      return builder.toString();
-    } else {
-      return null;
-    }
-  }
-
-  public String toString() {
-    final StringBuilder str = new StringBuilder();
-    for (final LayoutToken token : tokens) {
-      str.append(token);
-      str.append(";");
-    }
-    return str.toString();
-  }
-
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java
index 91bc6c1..fe2a31e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java
@@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory;
 import java.io.Serializable;
 
 /**
- * In JSPs the class {@link org.apache.myfaces.tobago.layout.MeasureEditor} will convert the string literals.
+ * In PDLs the class {@link org.apache.myfaces.tobago.layout.MeasureEditor} will convert the string literals.
  */
 public final class Measure implements Serializable {
 
@@ -35,80 +35,90 @@ public final class Measure implements Serializable {
   private static final Logger LOG = LoggerFactory.getLogger(Measure.class);
 
   public static final Measure ZERO = valueOf(0);
+  public static final Measure AUTO = valueOf("auto");
+  public static final Measure FRACTION1 = valueOf("1fr");
 
-  // todo: refactor and consolidate with LayoutToken
-
-  private final Double d;
-  private final Integer i;
+  private final float value;
   private final Unit unit;
 
+  private Measure() {
+    this.value = 0;
+    this.unit = Unit.AUTO;
+  }
+
   public Measure(int i, Unit unit) {
-    this.d = null;
-    this.i = i;
+    this.value = i;
     this.unit = unit;
   }
 
   public Measure(double d, Unit unit) {
-    this.d = d;
-    this.i = null;
+    this.value = (float) d;
     this.unit = unit;
   }
 
   public Measure(String string, Unit unit) {
-    if (string.contains(".")) {
-      this.d = Double.parseDouble(string);
-      this.i = null;
-    } else {
-      this.d = null;
-      this.i = Integer.parseInt(string);
-    }
+    this.value = Float.parseFloat(string);
     this.unit = unit;
   }
 
-  public static Measure valueOf(final Measure value) {
-    if (value == null) {
+  public static Measure valueOf(final Measure measure) {
+    if (measure == null) {
       return ZERO;
     }
-    return value;
+    return measure;
   }
 
   public static Measure valueOf(final int value) {
     return new Measure(value, Unit.PX);
   }
 
-  public static Measure valueOf(final Integer value) {
-    if (value == null) {
+  public static Measure valueOf(final Integer i) {
+    if (i == null) {
       return ZERO;
     }
-    return valueOf(value.intValue());
+    return valueOf(i.intValue());
   }
 
-  public static Measure valueOf(final Number value) {
-    if (value == null) {
+  public static Measure valueOf(final Number n) {
+    if (n == null) {
       return ZERO;
     }
-    return valueOf(value.doubleValue());
+    return valueOf(n.doubleValue());
   }
 
-  public static Measure valueOf(final String value) {
+  public static Measure valueOf(final String s) {
+    return valueOf(s, Unit.PX);
+  }
+
+  public static Measure valueOf(final String s, final Unit defaultUnit) {
     try {
-      if (StringUtils.isEmpty(value)) {
+      if (StringUtils.isEmpty(s)) {
         return null;
       }
-      final int length = value.length();
-      if (value.endsWith("%")) {
-        return new Measure(value.substring(0, length - 1), Unit.PERCENT);
+      final int length = s.length();
+      if (s.endsWith("%")) {
+        return new Measure(s.substring(0, length - 1), Unit.PERCENT);
+      }
+      if (s.endsWith("*")) {
+        if (s.length() == 1) {
+          return new Measure(1, Unit.FR);
+        } else {
+          return new Measure(s.substring(0, length - 1), Unit.FR);
+        }
+      }
+      if (s.equals("auto")) {
+        return new Measure();
       }
       for (int i = 4; i >= 2; i--) {
         final int pos = length - i;
-        if (length >= i && Character.isLetter(value.charAt(pos))) {
-          return new Measure(value.substring(0, pos), Unit.valueOf(value.substring(pos).toUpperCase()));
+        if (length >= i && Character.isLetter(s.charAt(pos))) {
+          return new Measure(s.substring(0, pos), Unit.valueOf(s.substring(pos).toUpperCase()));
         }
       }
-      return new Measure(value, Unit.PX);
+      return new Measure(s, defaultUnit);
 
     } catch (final RuntimeException e) {
-      LOG.warn("Can't parse to any measure: '" + value + "'");
+      LOG.warn("Can't parse to any measure: '" + s + "'");
     }
     return null;
   }
@@ -130,7 +140,25 @@ public final class Measure implements Serializable {
   }
 
   public String serialize() {
-    return "" + (i != null ? i : "") + (d != null ? d : "") + unit.getValue();
+    StringBuilder builder = new StringBuilder();
+    if (unit != Unit.AUTO) {
+      builder.append(value);
+    }
+    final int length = builder.length();
+    if (length >= 3 && builder.charAt(length - 1) == '0' && builder.charAt(length - 2) == '.') {
+      builder.deleteCharAt(length - 1);
+      builder.deleteCharAt(length - 2);
+    }
+    builder.append(unit.getValue());
+    return builder.toString();
+  }
+
+  public float getValue() {
+    return value;
+  }
+
+  public Unit getUnit() {
+    return unit;
   }
 
   public String toString() {
@@ -148,20 +176,15 @@ public final class Measure implements Serializable {
 
     Measure measure = (Measure) o;
 
-    if (d != null ? !d.equals(measure.d) : measure.d != null) {
-      return false;
-    }
-    if (i != null ? !i.equals(measure.i) : measure.i != null) {
+    if (Float.compare(measure.value, value) != 0) {
       return false;
     }
     return unit == measure.unit;
-
   }
 
   @Override
   public int hashCode() {
-    int result = d != null ? d.hashCode() : 0;
-    result = 31 * result + (i != null ? i.hashCode() : 0);
+    int result = (value != +0.0f ? Float.floatToIntBits(value) : 0);
     result = 31 * result + unit.hashCode();
     return result;
   }
@@ -182,7 +205,10 @@ public final class Measure implements Serializable {
     VH, // Relative to 1% of the height of the viewport*
     VMIN, // Relative to 1% of viewport's* smaller dimension
     VMAX, // Relative to 1% of viewport's* larger dimension
-    PERCENT;
+    PERCENT,
+    FR, // Fraction - same as * in classic Tobago
+    SEG, // Number of used columns in segment layout (Tobago specific)
+    AUTO; // Marker for CSS 'auto', not a regular measure
 
     private final String value;
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java
deleted file mode 100644
index 41f535b..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-/**
- * @since Tobago 3.0. Was renamed from PixelLayoutToken, because it's generalization.
- */
-public class MeasureLayoutToken extends LayoutToken {
-
-  private final Measure measure;
-
-  public MeasureLayoutToken(final String measure) {
-    // here we cannot use this(PixelMeasure.pixelValueOf(pixel)), because of class initialization problems
-    this(Measure.valueOf(measure));
-    if (this.measure == null) {
-      throw new NumberFormatException(measure);
-    }
-  }
-
-  public MeasureLayoutToken(final Measure measure) {
-    this.measure = measure;
-  }
-
-  public Measure getMeasure() {
-    return measure;
-  }
-
-  public String toString() {
-    return measure.toString();
-  }
-
-  public boolean equals(final Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    final MeasureLayoutToken that = (MeasureLayoutToken) o;
-
-    return measure.equals(that.measure);
-
-  }
-
-  public int hashCode() {
-    return measure.hashCode();
-  }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureList.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureList.java
new file mode 100644
index 0000000..23349f8
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureList.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public class MeasureList implements Iterable<Measure> {
+
+  protected List<Measure> list = new ArrayList<>();
+
+  public MeasureList() {
+  }
+
+  @Override
+  public Iterator<Measure> iterator() {
+    return list.iterator();
+  }
+
+  public static MeasureList parse(final String string) {
+    final MeasureList measureList = new MeasureList();
+    final StringTokenizer tokenizer = new StringTokenizer(string, "; ");
+
+    while (tokenizer.hasMoreTokens()) {
+      final Measure token = Measure.valueOf(tokenizer.nextToken().trim());
+      measureList.list.add(token);
+    }
+    return measureList;
+  }
+
+  public int getSize() {
+    return list.size();
+  }
+
+  public Measure get(int i) {
+    return list.get(i);
+  }
+
+  public void add(final Measure measure) {
+    list.add(measure);
+  }
+
+  public String serialize() {
+    final StringBuilder str = new StringBuilder();
+    for (final Measure measure : list) {
+      str.append(measure);
+      str.append(" ");
+    }
+    return str.toString();
+  }
+
+  public String toString() {
+    return serialize();
+  }
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureListEditor.java
similarity index 65%
rename from tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java
rename to tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureListEditor.java
index 25a86e2..08467c8 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureListEditor.java
@@ -19,11 +19,24 @@
 
 package org.apache.myfaces.tobago.layout;
 
-public final class AutoLayoutToken extends LayoutToken {
-  
-  public static final AutoLayoutToken INSTANCE = new AutoLayoutToken();
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-  public String toString() {
-    return "auto";
+import java.beans.PropertyEditorSupport;
+
+/**
+ * Converter for {@link Measure}
+ */
+public class MeasureListEditor extends PropertyEditorSupport {
+
+  private static final Logger LOG = LoggerFactory.getLogger(MeasureListEditor.class);
+
+  @Override
+  public void setAsText(final String text) throws IllegalArgumentException {
+
+    LOG.info("XXX " + getSource());
+
+    setValue(MeasureList.parse(text));
   }
+
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java
deleted file mode 100644
index 9d1a6c8..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-public class RelativeLayoutToken extends LayoutToken {
-
-  static final String SUFFIX = "*";
-
-  public static final String DEFAULT_TOKEN_STRING = "1*";
-  public static final RelativeLayoutToken DEFAULT_INSTANCE = new RelativeLayoutToken(1);
-
-  private int factor = 1;
-
-  public RelativeLayoutToken(final int factor) {
-    this.factor = factor;
-  }
-
-  public int getFactor() {
-    return factor;
-  }
-
-  public String toString() {
-    return factor + SUFFIX;
-  }
-
-  public boolean equals(final Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    final RelativeLayoutToken that = (RelativeLayoutToken) o;
-
-    if (factor != that.factor) {
-      return false;
-    }
-
-    return true;
-  }
-
-  public int hashCode() {
-    return factor;
-  }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentLayoutToken.java
deleted file mode 100644
index a48eab3..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentLayoutToken.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-public class SegmentLayoutToken extends LayoutToken {
-
-  private int columnSize = 1;
-
-  public SegmentLayoutToken(final int columnSize) {
-    if (columnSize < 1) {
-      this.columnSize = 1;
-    } else if (columnSize > 12) {
-      this.columnSize = 12;
-    } else {
-      this.columnSize = columnSize;
-    }
-  }
-
-  public int getColumnSize() {
-    return columnSize;
-  }
-
-  public String toString() {
-    return String.valueOf(columnSize);
-  }
-
-  public boolean equals(final Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    final SegmentLayoutToken that = (SegmentLayoutToken) o;
-
-    if (columnSize != that.columnSize) {
-      return false;
-    }
-
-    return true;
-  }
-
-  public int hashCode() {
-    return columnSize;
-  }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureList.java
similarity index 59%
rename from tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java
rename to tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureList.java
index a893627..dde5925 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureList.java
@@ -19,8 +19,22 @@
 
 package org.apache.myfaces.tobago.layout;
 
-public final class HideLayoutToken extends LayoutToken {
-  public String toString() {
-    return "hide";
+import org.apache.myfaces.tobago.apt.annotation.Preliminary;
+
+import java.util.StringTokenizer;
+
+@Preliminary
+public final class SegmentMeasureList extends MeasureList {
+
+  public static SegmentMeasureList parse(final String string) {
+    final SegmentMeasureList measureList = new SegmentMeasureList();
+    final StringTokenizer tokenizer = new StringTokenizer(string, "; ");
+
+    while (tokenizer.hasMoreTokens()) {
+      final Measure token = Measure.valueOf(tokenizer.nextToken().trim(), Measure.Unit.SEG);
+      measureList.list.add(token);
+    }
+    return measureList;
   }
+
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureListEditor.java
similarity index 60%
rename from tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java
rename to tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureListEditor.java
index 1e6bb21..8cdef03 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/SegmentMeasureListEditor.java
@@ -19,8 +19,26 @@
 
 package org.apache.myfaces.tobago.layout;
 
-public final class MinimumLayoutToken extends LayoutToken {
-  public String toString() {
-    return "minimum";
+import org.apache.myfaces.tobago.apt.annotation.Preliminary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.beans.PropertyEditorSupport;
+
+/**
+ * Converter for {@link Measure}
+ */
+@Preliminary
+public class SegmentMeasureListEditor extends PropertyEditorSupport {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SegmentMeasureListEditor.class);
+
+  @Override
+  public void setAsText(final String text) throws IllegalArgumentException {
+
+    LOG.info("XXX " + getSource());
+
+    setValue(SegmentMeasureList.parse(text));
   }
+
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
index ff6ab55..d6e8fec 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
@@ -21,14 +21,11 @@ package org.apache.myfaces.tobago.renderkit.css;
 
 import org.apache.myfaces.tobago.component.Attributes;
 import org.apache.myfaces.tobago.layout.AlignItems;
-import org.apache.myfaces.tobago.layout.AutoLayoutToken;
 import org.apache.myfaces.tobago.layout.JustifyContent;
-import org.apache.myfaces.tobago.layout.LayoutToken;
-import org.apache.myfaces.tobago.layout.LayoutTokens;
 import org.apache.myfaces.tobago.layout.Margin;
 import org.apache.myfaces.tobago.layout.MarginTokens;
-import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
-import org.apache.myfaces.tobago.layout.SegmentLayoutToken;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.apache.myfaces.tobago.layout.TextAlign;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.slf4j.Logger;
@@ -592,11 +589,11 @@ public enum BootstrapClass implements CssItem {
         OFFSET_XL_6, OFFSET_XL_7, OFFSET_XL_8, OFFSET_XL_9, OFFSET_XL_10, OFFSET_XL_11
     };
 
-    private final LayoutTokens extraSmall;
-    private final LayoutTokens small;
-    private final LayoutTokens medium;
-    private final LayoutTokens large;
-    private final LayoutTokens extraLarge;
+    private final MeasureList extraSmall;
+    private final MeasureList small;
+    private final MeasureList medium;
+    private final MeasureList large;
+    private final MeasureList extraLarge;
     private final MarginTokens marginExtraSmall;
     private final MarginTokens marginSmall;
     private final MarginTokens marginMedium;
@@ -605,12 +602,12 @@ public enum BootstrapClass implements CssItem {
 
     private int index = 0;
 
-    public Generator(final LayoutTokens extraSmall, final LayoutTokens small, final LayoutTokens medium,
-        final LayoutTokens large, final LayoutTokens extraLarge,
-        final MarginTokens marginExtraSmall, final MarginTokens marginSmall, final MarginTokens marginMedium,
-        final MarginTokens marginLarge, final MarginTokens marginExtraLarge) {
+    public Generator(final MeasureList extraSmall, final MeasureList small, final MeasureList medium,
+                     final MeasureList large, final MeasureList extraLarge,
+                     final MarginTokens marginExtraSmall, final MarginTokens marginSmall, final MarginTokens marginMedium,
+                     final MarginTokens marginLarge, final MarginTokens marginExtraLarge) {
       if (extraSmall == null && small == null && medium == null && large == null && extraLarge == null) {
-        this.extraSmall = LayoutTokens.parse("*");
+        this.extraSmall = MeasureList.parse("*"); // TBD: is this needed? if yes, use Measure.FRACTION1
       } else {
         this.extraSmall = extraSmall;
       }
@@ -656,17 +653,18 @@ public enum BootstrapClass implements CssItem {
       return result.toArray(new BootstrapClass[result.size()]);
     }
 
-    private void generate(final List<BootstrapClass> result, final LayoutTokens tokens,
+    private void generate(
+        final List<BootstrapClass> result, final MeasureList tokens,
         final Map<String, Object> attributes, final Attributes attribute) {
       Object overwrite = attributes.get(attribute.name());
 
       if (overwrite != null) {
-        final LayoutToken layoutToken = LayoutTokens.parseToken((String) overwrite);
-        final BootstrapClass bootstrapClass = valueOf(layoutToken, attribute);
+        final Measure measure = Measure.valueOf(overwrite);
+        final BootstrapClass bootstrapClass = valueOf(measure, attribute);
         result.add(bootstrapClass);
       } else if (tokens != null) {
-        final LayoutToken layoutToken = tokens.get(index % tokens.getSize());
-        final BootstrapClass bootstrapClass = valueOf(layoutToken, attribute);
+        final Measure measure = tokens.get(index % tokens.getSize());
+        final BootstrapClass bootstrapClass = valueOf(measure, attribute);
         result.add(bootstrapClass);
       }
     }
@@ -697,16 +695,17 @@ public enum BootstrapClass implements CssItem {
     }
   }
 
-  public static BootstrapClass valueOf(LayoutToken layoutToken, Attributes attributes) {
+  public static BootstrapClass valueOf(Measure measure, Attributes attributes) {
     final String size = getSizeSuffix(attributes);
 
-    if (layoutToken instanceof RelativeLayoutToken) {
+    if (measure.getUnit() == Measure.Unit.FR) {
       return valueOf("COL" + size);
-    } else if (layoutToken instanceof AutoLayoutToken) {
+    } else if (measure.getUnit() == Measure.Unit.AUTO) {
       return valueOf("COL" + size + "_AUTO");
-    } else if (layoutToken instanceof SegmentLayoutToken) {
-      SegmentLayoutToken segmentLayoutToken = (SegmentLayoutToken) layoutToken;
-      return valueOf("COL" + size + "_" + segmentLayoutToken.getColumnSize());
+    } else if (measure.getUnit() == Measure.Unit.SEG) {
+      final float value = measure.getValue();
+      return valueOf(
+          "COL" + size + "_" + (value == (long) value ? Long.toString((long) value) : Float.toString(value)));
     } else {
       return null;
     }
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java
index 6e112e5..ace1eaf 100644
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java
@@ -19,7 +19,7 @@
 
 package org.apache.myfaces.tobago.internal.layout;
 
-import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.MeasureList;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -28,7 +28,7 @@ public class GridUnitTest {
   @Test
   public void test1x1() {
 
-    final Grid grid = new Grid(LayoutTokens.parse("*"), LayoutTokens.parse("*"));
+    final Grid grid = new Grid(MeasureList.parse("*"), MeasureList.parse("*"));
     Assert.assertEquals(1, grid.getColumns().getSize());
     Assert.assertEquals(1, grid.getRows().getSize());
     Assert.assertEquals(""
@@ -89,7 +89,7 @@ public class GridUnitTest {
   @Test
   public void test2x1() {
 
-    final Grid grid = new Grid(LayoutTokens.parse("*;*"), LayoutTokens.parse("*"));
+    final Grid grid = new Grid(MeasureList.parse("*;*"), MeasureList.parse("*"));
     Assert.assertEquals(2, grid.getColumns().getSize());
     Assert.assertEquals(1, grid.getRows().getSize());
     Assert.assertEquals(""
@@ -184,7 +184,7 @@ public class GridUnitTest {
   @Test
   public void test5x5() {
 
-    final Grid grid = new Grid(LayoutTokens.parse("*;*;*;*;*"), LayoutTokens.parse("*;*;*;*;*"));
+    final Grid grid = new Grid(MeasureList.parse("*;*;*;*;*"), MeasureList.parse("*;*;*;*;*"));
     Assert.assertEquals(5, grid.getColumns().getSize());
     Assert.assertEquals(5, grid.getRows().getSize());
     Assert.assertEquals(""
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java
deleted file mode 100644
index 30c9ebb..0000000
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.myfaces.tobago.layout;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class LayoutTokensUnitTest {
-
-  @Test
-  public void testIsRelativeToken() {
-    Assert.assertTrue(LayoutTokens.isRelativeToken("3*"));
-  }
-
-  @Test
-  public void testIsNumberAndSuffix() {
-    Assert.assertTrue(LayoutTokens.isNumberAndSuffix("34cm", "cm"));
-    Assert.assertFalse(LayoutTokens.isNumberAndSuffix("acm", "cm"));
-    Assert.assertFalse(LayoutTokens.isNumberAndSuffix("cm", "cm"));
-  }
-
-  @Test
-  public void testIsSegmentLayoutToken() {
-    Assert.assertTrue(LayoutTokens.isSegmentLayoutToken("3"));
-    Assert.assertFalse(LayoutTokens.isSegmentLayoutToken("3*"));
-    Assert.assertFalse(LayoutTokens.isSegmentLayoutToken("3cm"));
-  }
-
-  @Test
-  public void testParseToken() {
-    Assert.assertEquals(AutoLayoutToken.INSTANCE, LayoutTokens.parseToken(null));
-    Assert.assertEquals(RelativeLayoutToken.DEFAULT_INSTANCE, LayoutTokens.parseToken("*"));
-    Assert.assertEquals(new RelativeLayoutToken(3), LayoutTokens.parseToken("3*"));
-    Assert.assertEquals(new MeasureLayoutToken("33%"), LayoutTokens.parseToken("33%"));
-    Assert.assertEquals(new MeasureLayoutToken("120px"), LayoutTokens.parseToken("120px"));
-    Assert.assertEquals(new MeasureLayoutToken("0px"), LayoutTokens.parseToken("0px"));
-    Assert.assertEquals(new SegmentLayoutToken(8), LayoutTokens.parseToken("8"));
-  }
-}
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java
index efba114..d476834 100644
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java
@@ -49,6 +49,12 @@ public class MeasureUnitTest {
     Assert.assertEquals("13.7vmin", "" + Measure.valueOf("13.7vmin"));
     Assert.assertEquals("13.7vmax", "" + Measure.valueOf("13.7vmax"));
     Assert.assertEquals("13.7%", "" + Measure.valueOf("13.7%"));
+    Assert.assertEquals("13fr", "" + Measure.valueOf("13*"));
+    Assert.assertEquals("13fr", "" + Measure.valueOf("13fr"));
+    Assert.assertEquals("auto", "" + Measure.valueOf("auto"));
+    Assert.assertEquals("13fr", "" + Measure.valueOf("13*"));
+    Assert.assertEquals("1fr", "" + Measure.valueOf("*"));
+    Assert.assertEquals("1seg", "" + Measure.valueOf("1seg"));
   }
 
   @Test
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/60-split/split-layout.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/60-split/split-layout.xhtml
index ee39dc4..9c8157e 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/60-split/split-layout.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/60-split/split-layout.xhtml
@@ -20,19 +20,25 @@
 <ui:composition template="/main.xhtml"
                 xmlns:f="http://java.sun.com/jsf/core"
                 xmlns:ui="http://java.sun.com/jsf/facelets"
-                xmlns:tc="http://myfaces.apache.org/tobago/component">
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:demo="http://myfaces.apache.org/tobago/example/demo">
 
   <ui:param name="title" value="SplitLayout Example"/>
 
-  <tc:splitLayout columns="1*;1*">
+  <p><span class="#{demo:bootstrapClass('BADGE')} #{demo:bootstrapClass('BADGE_DANGER')}">Warning!</span>
+  Preliminary implementation, work in progress!</p>
+
+  <tc:splitLayout columns="2fr;1fr;1fr">
     <tc:panel>
-     <p>Sample Text: Laut dem Debian-Projekt kann der Fehler "ein unvorhersehbares Systemverhalten verursachen",
-       wie etwa Fehlverhalten von Anwendung und des Systems, Datenveränderungen oder gar Datenverlust.
-       Einige Nutzer von Debian Stable alias Stretch seien von dem Fehler betroffen, weshalb nun die
-       Warnung veröffentlicht worden ist.</p>
+      <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore
+        et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
+        Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
+        consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+        sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
+        takimata sanctus est Lorem ipsum dolor sit amet.</p>
     </tc:panel>
-    <tc:textarea value="Text" labelLayout="none"/>
-    <!--<tc:textarea value="Text" labelLayout="none"/>-->
+    <tc:textarea value="Text 1" labelLayout="none"/>
+<!--    <tc:textarea value="Text 2" labelLayout="none"/> -->
   </tc:splitLayout>
 
   <tc:splitLayout columns="1*;4*;1*">
diff --git a/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg b/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg
index 4cd5b2d..0fa1394 100644
--- a/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg
+++ b/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg
@@ -408,6 +408,10 @@ DoubleProperty(property) ::= <<
 <NormalProperty(property)>
 >>
 
+NumberProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
 MethodExpressionProperty(property) ::= <<
 
 /**
@@ -514,6 +518,14 @@ public void set<property.upperCamelCaseName>(<property.type> <property.propertyN
 }
 >>
 
+MeasureListProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+SegmentMeasureListProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
 MarkupProperty(property) ::= <<
 
 <checkDeprecated(property)>

-- 
To stop receiving notification emails like this one, please contact
['"commits@myfaces.apache.org" <co...@myfaces.apache.org>'].