You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by hn...@apache.org on 2017/09/29 11:13:11 UTC

[myfaces-tobago] branch master updated: TOBAGO-1789 New (Bootstrap beta) offset concept for tc:segmentLayout * implement margin concept for segmentLayout / segmentLayoutConstraints

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

hnoeth 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 8bba4ff  TOBAGO-1789 New (Bootstrap beta) offset concept for tc:segmentLayout * implement margin concept for segmentLayout / segmentLayoutConstraints
8bba4ff is described below

commit 8bba4fff20088d67b7185494313118abc26dd078
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Fri Sep 29 13:12:59 2017 +0200

    TOBAGO-1789 New (Bootstrap beta) offset concept for tc:segmentLayout
    * implement margin concept for segmentLayout / segmentLayoutConstraints
---
 .../myfaces/tobago/component/Attributes.java       |  40 ++++++
 .../facelets/SegmentLayoutConstraintHandler.java   |  69 ++++------
 .../renderkit/renderer/SegmentLayoutRenderer.java  |   8 +-
 .../SegmentLayoutConstraintTagDeclaration.java     |  45 ++++++-
 .../component/SegmentLayoutTagDeclaration.java     |  48 ++++++-
 .../org/apache/myfaces/tobago/layout/Margin.java   |  32 +++++
 .../apache/myfaces/tobago/layout/MarginTokens.java |  74 +++++++++++
 .../tobago/renderkit/css/BootstrapClass.java       | 143 ++++++++++++++++-----
 .../50-migration/96-migration/migration40.xhtml    |  66 ++++++----
 .../16-layout/30-segment/segment-layout.xhtml      |  48 +++++--
 10 files changed, 449 insertions(+), 124 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 514b25d..21cf93b 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
@@ -137,14 +137,34 @@ public enum Attributes {
   /**
    * Used by a layout manager
    */
+  marginExtraLarge,
+  /**
+   * Used by a layout manager
+   */
+  marginExtraSmall,
+  /**
+   * Used by a layout manager
+   */
+  marginLarge,
+  /**
+   * Used by a layout manager
+   */
   marginLeft,
   /**
    * Used by a layout manager
    */
+  marginMedium,
+  /**
+   * Used by a layout manager
+   */
   marginRight,
   /**
    * Used by a layout manager
    */
+  marginSmall,
+  /**
+   * Used by a layout manager
+   */
   marginTop,
   marked,
   markup,
@@ -187,6 +207,26 @@ public enum Attributes {
   /**
    * Used by a layout manager
    */
+  overwriteMarginExtraLarge,
+  /**
+   * Used by a layout manager
+   */
+  overwriteMarginExtraSmall,
+  /**
+   * Used by a layout manager
+   */
+  overwriteMarginLarge,
+  /**
+   * Used by a layout manager
+   */
+  overwriteMarginMedium,
+  /**
+   * Used by a layout manager
+   */
+  overwriteMarginSmall,
+  /**
+   * Used by a layout manager
+   */
   overwriteMedium,
   /**
    * Used by a layout manager
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutConstraintHandler.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutConstraintHandler.java
index e50c8f7..87208a3 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutConstraintHandler.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutConstraintHandler.java
@@ -27,7 +27,6 @@ import javax.faces.view.facelets.TagAttribute;
 import javax.faces.view.facelets.TagConfig;
 import javax.faces.view.facelets.TagHandler;
 import java.io.IOException;
-import java.util.Map;
 
 public class SegmentLayoutConstraintHandler extends TagHandler {
 
@@ -36,6 +35,11 @@ public class SegmentLayoutConstraintHandler extends TagHandler {
   private final TagAttribute overwriteMedium;
   private final TagAttribute overwriteLarge;
   private final TagAttribute overwriteExtraLarge;
+  private final TagAttribute overwriteMarginExtraSmall;
+  private final TagAttribute overwriteMarginSmall;
+  private final TagAttribute overwriteMarginMedium;
+  private final TagAttribute overwriteMarginLarge;
+  private final TagAttribute overwriteMarginExtraLarge;
 
   public SegmentLayoutConstraintHandler(TagConfig config) {
     super(config);
@@ -44,54 +48,35 @@ public class SegmentLayoutConstraintHandler extends TagHandler {
     overwriteMedium = getAttribute(Attributes.medium.getName());
     overwriteLarge = getAttribute(Attributes.large.getName());
     overwriteExtraLarge = getAttribute(Attributes.extraLarge.getName());
+    overwriteMarginExtraSmall = getAttribute(Attributes.marginExtraSmall.getName());
+    overwriteMarginSmall = getAttribute(Attributes.marginSmall.getName());
+    overwriteMarginMedium = getAttribute(Attributes.marginMedium.getName());
+    overwriteMarginLarge = getAttribute(Attributes.marginLarge.getName());
+    overwriteMarginExtraLarge = getAttribute(Attributes.marginExtraLarge.getName());
   }
 
   @Override
   public void apply(FaceletContext faceletContext, UIComponent parent) throws IOException {
-    final Map<String, Object> attributes = parent.getAttributes();
+    apply(faceletContext, parent, overwriteExtraSmall, Attributes.overwriteExtraSmall, Integer.TYPE);
+    apply(faceletContext, parent, overwriteSmall, Attributes.overwriteSmall, Integer.TYPE);
+    apply(faceletContext, parent, overwriteMedium, Attributes.overwriteMedium, Integer.TYPE);
+    apply(faceletContext, parent, overwriteLarge, Attributes.overwriteLarge, Integer.TYPE);
+    apply(faceletContext, parent, overwriteExtraLarge, Attributes.overwriteExtraLarge, Integer.TYPE);
 
-    if (overwriteExtraSmall != null) {
-      if (overwriteExtraSmall.isLiteral()) {
-        attributes.put(Attributes.overwriteExtraSmall.getName(), overwriteExtraSmall.getValue());
-      } else {
-        parent.setValueExpression(Attributes.overwriteExtraSmall.getName(),
-            overwriteExtraSmall.getValueExpression(faceletContext, Integer.TYPE));
-      }
-    }
-
-    if (overwriteSmall != null) {
-      if (overwriteSmall.isLiteral()) {
-        attributes.put(Attributes.overwriteSmall.getName(), overwriteSmall.getValue());
-      } else {
-        parent.setValueExpression(Attributes.overwriteSmall.getName(),
-            overwriteSmall.getValueExpression(faceletContext, Integer.TYPE));
-      }
-    }
-
-    if (overwriteMedium != null) {
-      if (overwriteMedium.isLiteral()) {
-        attributes.put(Attributes.overwriteMedium.getName(), overwriteMedium.getValue());
-      } else {
-        parent.setValueExpression(Attributes.overwriteMedium.getName(),
-            overwriteMedium.getValueExpression(faceletContext, Integer.TYPE));
-      }
-    }
-
-    if (overwriteLarge != null) {
-      if (overwriteLarge.isLiteral()) {
-        attributes.put(Attributes.overwriteLarge.getName(), overwriteLarge.getValue());
-      } else {
-        parent.setValueExpression(Attributes.overwriteLarge.getName(),
-            overwriteLarge.getValueExpression(faceletContext, Integer.TYPE));
-      }
-    }
+    apply(faceletContext, parent, overwriteMarginExtraSmall, Attributes.overwriteMarginExtraSmall, String.class);
+    apply(faceletContext, parent, overwriteMarginSmall, Attributes.overwriteMarginSmall, String.class);
+    apply(faceletContext, parent, overwriteMarginMedium, Attributes.overwriteMarginMedium, String.class);
+    apply(faceletContext, parent, overwriteMarginLarge, Attributes.overwriteMarginLarge, String.class);
+    apply(faceletContext, parent, overwriteMarginExtraLarge, Attributes.overwriteMarginExtraLarge, String.class);
+  }
 
-    if (overwriteExtraLarge != null) {
-      if (overwriteExtraLarge.isLiteral()) {
-        attributes.put(Attributes.overwriteExtraLarge.getName(), overwriteExtraLarge.getValue());
+  private void apply(FaceletContext faceletContext, UIComponent parent, final TagAttribute tagAttribute,
+      final Attributes attribute, final Class type) {
+    if (tagAttribute != null) {
+      if (tagAttribute.isLiteral()) {
+        parent.getAttributes().put(attribute.getName(), tagAttribute.getValue());
       } else {
-        parent.setValueExpression(Attributes.overwriteExtraLarge.getName(),
-            overwriteExtraLarge.getValueExpression(faceletContext, Integer.TYPE));
+        parent.setValueExpression(attribute.getName(), tagAttribute.getValueExpression(faceletContext, type));
       }
     }
   }
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 ad60cab..ad49997 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
@@ -24,6 +24,7 @@ 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;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
@@ -80,7 +81,12 @@ public class SegmentLayoutRenderer extends RendererBase {
         LayoutTokens.parse(segmentLayout.getSmall()),
         LayoutTokens.parse(segmentLayout.getMedium()),
         LayoutTokens.parse(segmentLayout.getLarge()),
-        LayoutTokens.parse(segmentLayout.getExtraLarge()));
+        LayoutTokens.parse(segmentLayout.getExtraLarge()),
+        MarginTokens.parse(segmentLayout.getMarginExtraSmall()),
+        MarginTokens.parse(segmentLayout.getMarginSmall()),
+        MarginTokens.parse(segmentLayout.getMarginMedium()),
+        MarginTokens.parse(segmentLayout.getMarginLarge()),
+        MarginTokens.parse(segmentLayout.getMarginExtraLarge()));
     for (UIComponent child : children) {
       if (child.isRendered()) {
         encodeChild(facesContext, writer, generator, child);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutConstraintTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutConstraintTagDeclaration.java
index 3cf0bad..bec344f 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutConstraintTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutConstraintTagDeclaration.java
@@ -22,6 +22,8 @@ package org.apache.myfaces.tobago.internal.taglib.component;
 import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
 import org.apache.myfaces.tobago.apt.annotation.Tag;
 import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.layout.Margin;
 
 import javax.el.ValueExpression;
 
@@ -34,28 +36,28 @@ public interface SegmentLayoutConstraintTagDeclaration {
 
   /**
    * Overwrite the default layout for extra small devices.
-   * Possible values are: integer value > 0, 'auto' or '*'.
+   * Possible values are: integer value > 0, 'auto' and '*'.
    */
   @TagAttribute
   void setExtraSmall(final ValueExpression extraSmall);
 
   /**
    * Overwrite the default layout for small devices.
-   * Possible values are: integer value > 0, 'auto' or '*'.
+   * Possible values are: integer value > 0, 'auto' and '*'.
    */
   @TagAttribute
   void setSmall(final ValueExpression small);
 
   /**
    * Overwrite the default layout for medium devices.
-   * Possible values are: integer value > 0, 'auto' or '*'.
+   * Possible values are: integer value > 0, 'auto' and '*'.
    */
   @TagAttribute
   void setMedium(final ValueExpression medium);
 
   /**
    * Overwrite the default layout for large devices.
-   * Possible values are: integer value > 0, 'auto' or '*'.
+   * Possible values are: integer value > 0, 'auto' and '*'.
    */
   @TagAttribute
   void setLarge(final ValueExpression large);
@@ -66,4 +68,39 @@ public interface SegmentLayoutConstraintTagDeclaration {
    */
   @TagAttribute
   void setExtraLarge(final ValueExpression extraLarge);
+
+  /**
+   * Overwrite the default margin for extra small devices.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(allowedValues = {Margin.NONE, Margin.LEFT, Margin.RIGHT, Margin.BOTH})
+  void setMarginExtraSmall(final ValueExpression overwriteMarginExtraSmall);
+
+  /**
+   * Overwrite the default margin for small devices.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(allowedValues = {Margin.NONE, Margin.LEFT, Margin.RIGHT, Margin.BOTH})
+  void setMarginSmall(final ValueExpression overwriteMarginSmall);
+
+  /**
+   * Overwrite the default margin for medium devices.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(allowedValues = {Margin.NONE, Margin.LEFT, Margin.RIGHT, Margin.BOTH})
+  void setMarginMedium(final ValueExpression overwriteMarginMedium);
+
+  /**
+   * Overwrite the default margin for large devices.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(allowedValues = {Margin.NONE, Margin.LEFT, Margin.RIGHT, Margin.BOTH})
+  void setMarginLarge(final ValueExpression overwriteMarginLarge);
+
+  /**
+   * Overwrite the default margin for extra large devices.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(allowedValues = {Margin.NONE, Margin.LEFT, Margin.RIGHT, Margin.BOTH})
+  void setMarginExtraLarge(final ValueExpression overwriteMarginExtraLarge);
 }
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 1243d1b..d8783bb 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
@@ -31,8 +31,9 @@ import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
 /**
  * Renders a layout using a 12 columns grid.
  * Find more information on how the grid works in the Twitter Bootstrap documentation.
- *
+ * <p>
  * If no attribute is defined, extraSmall="12" will be used as default.
+ *
  * @since 3.0.0
  */
 @Tag(name = "segmentLayout")
@@ -92,4 +93,49 @@ public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, Is
   @TagAttribute
   @UIComponentTagAttribute
   void setExtraLarge(String extraLarge);
+
+  /**
+   * The semicolon-separated definition of the column margins for extra small devices.
+   * Allowed values are: none, left, right, both
+   * Example: 'left;none;both'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setMarginExtraSmall(String marginExtraSmall);
+
+  /**
+   * The semicolon-separated definition of the column margins for small devices.
+   * Allowed values are: none, left, right, both
+   * Example: 'left;none;both'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setMarginSmall(String marginSmall);
+
+  /**
+   * The semicolon-separated definition of the column margins for medium devices.
+   * Allowed values are: none, left, right, both
+   * Example: 'left;none;both'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setMarginMedium(String marginMedium);
+
+  /**
+   * The semicolon-separated definition of the column margins for large devices.
+   * Allowed values are: none, left, right, both
+   * Example: 'left;none;both'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setMarginLarge(String marginLarge);
+
+  /**
+   * The semicolon-separated definition of the column margins for extra large devices.
+   * Allowed values are: none, left, right, both
+   * Example: 'left;none;both'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setMarginExtraLarge(String marginExtraLarge);
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Margin.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Margin.java
new file mode 100644
index 0000000..1372a76
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Margin.java
@@ -0,0 +1,32 @@
+/*
+ * 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 enum Margin {
+  none,
+  left,
+  right,
+  both;
+
+  public static final String NONE = "none";
+  public static final String LEFT = "left";
+  public static final String RIGHT = "right";
+  public static final String BOTH = "both";
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MarginTokens.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MarginTokens.java
new file mode 100644
index 0000000..896ecb8
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MarginTokens.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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public class MarginTokens {
+
+  private static final Logger LOG = LoggerFactory.getLogger(MarginTokens.class);
+
+  private List<Margin> margins = new ArrayList<>();
+
+  public int getSize() {
+    return margins.size();
+  }
+
+  public Margin get(final int index) {
+    return margins.get(index);
+  }
+
+  public void addMargin(Margin token) {
+    margins.add(token);
+  }
+
+  public List<Margin> getMargins() {
+    return margins;
+  }
+
+  public static MarginTokens parse(final String tokens) {
+    if (tokens == null) {
+      return null;
+    }
+    final MarginTokens marginTokens = new MarginTokens();
+    final StringTokenizer tokenizer = new StringTokenizer(tokens, ";");
+
+    while (tokenizer.hasMoreTokens()) {
+      final String token = tokenizer.nextToken().trim();
+      marginTokens.addMargin(parseToken(token));
+    }
+    return marginTokens;
+  }
+
+  public static Margin parseToken(final String token) {
+    for (Margin margin : Margin.values()) {
+      if (margin.name().equals(token)) {
+        return margin;
+      }
+    }
+    LOG.error("Error parsing layout token '" + token + "'! Using 'none' instead.");
+    return Margin.none;
+  }
+}
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 9b7bd96..473d809 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
@@ -25,6 +25,8 @@ 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.TextAlign;
@@ -291,18 +293,31 @@ public enum BootstrapClass implements CssItem {
   JUSTIFY_CONTENT_END("justify-content-end"),
   JUSTIFY_CONTENT_START("justify-content-start"),
   ML_AUTO("ml-auto"),
+  ML_LG_AUTO("ml-lg-auto"),
+  ML_MD_AUTO("ml-md-auto"),
+  ML_SM_AUTO("ml-sm-auto"),
+  ML_XL_AUTO("ml-xl-auto"),
   MODAL("modal"),
   MODAL_CONTENT("modal-content"),
   MODAL_DIALOG("modal-dialog"),
   MODAL_LG("modal-lg"),
   MODAL_SM("modal-sm"),
   MR_AUTO("mr-auto"),
+  MR_LG_AUTO("mr-lg-auto"),
+  MR_MD_AUTO("mr-md-auto"),
+  MR_SM_AUTO("mr-sm-auto"),
+  MR_XL_AUTO("mr-xl-auto"),
   MY_LG_0("my-lg-0"),
   MY_LG_1("my-lg-1"),
   MY_LG_2("my-lg-2"),
   MY_LG_3("my-lg-3"),
   MY_LG_4("my-lg-4"),
   MY_LG_5("my-lg-5"),
+  MX_AUTO("mx-auto"),
+  MX_LG_AUTO("mx-lg-auto"),
+  MX_MD_AUTO("mx-md-auto"),
+  MX_SM_AUTO("mx-sm-auto"),
+  MX_XL_AUTO("mx-xl-auto"),
   NAV("nav"),
   NAV_ITEM("nav-item"),
   NAV_LINK("nav-link"),
@@ -454,11 +469,18 @@ public enum BootstrapClass implements CssItem {
     private final LayoutTokens medium;
     private final LayoutTokens large;
     private final LayoutTokens extraLarge;
+    private final MarginTokens marginExtraSmall;
+    private final MarginTokens marginSmall;
+    private final MarginTokens marginMedium;
+    private final MarginTokens marginLarge;
+    private final MarginTokens marginExtraLarge;
 
     private int index = 0;
 
     public Generator(final LayoutTokens extraSmall, final LayoutTokens small, final LayoutTokens medium,
-        final LayoutTokens large, final LayoutTokens extraLarge) {
+        final LayoutTokens large, final LayoutTokens 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("*");
       } else {
@@ -468,6 +490,11 @@ public enum BootstrapClass implements CssItem {
       this.medium = medium;
       this.large = large;
       this.extraLarge = extraLarge;
+      this.marginExtraSmall = marginExtraSmall;
+      this.marginSmall = marginSmall;
+      this.marginMedium = marginMedium;
+      this.marginLarge = marginLarge;
+      this.marginExtraLarge = marginExtraLarge;
     }
 
     public void reset() {
@@ -479,55 +506,55 @@ public enum BootstrapClass implements CssItem {
     }
 
     public BootstrapClass[] generate(final UIComponent child) {
-      ArrayList<BootstrapClass> result = new ArrayList<>(5);
+      ArrayList<BootstrapClass> result = new ArrayList<>(10);
       final Map<String, Object> attributes = child.getAttributes();
-      generate(result, extraSmall, Attributes.extraSmall, attributes.get(Attributes.overwriteExtraSmall.name()));
-      generate(result, small, Attributes.small, attributes.get(Attributes.overwriteSmall.name()));
-      generate(result, medium, Attributes.medium, attributes.get(Attributes.overwriteMedium.name()));
-      generate(result, large, Attributes.large, attributes.get(Attributes.overwriteLarge.name()));
-      generate(result, extraLarge, Attributes.extraLarge, attributes.get(Attributes.overwriteExtraLarge.name()));
+      generate(result, extraSmall, attributes, Attributes.overwriteExtraSmall);
+      generate(result, small, attributes, Attributes.overwriteSmall);
+      generate(result, medium, attributes, Attributes.overwriteMedium);
+      generate(result, large, attributes, Attributes.overwriteLarge);
+      generate(result, extraLarge, attributes, Attributes.overwriteExtraLarge);
+
+      generate(result, marginExtraSmall, attributes, Attributes.overwriteMarginExtraSmall);
+      generate(result, marginSmall, attributes, Attributes.overwriteMarginSmall);
+      generate(result, marginMedium, attributes, Attributes.overwriteMarginMedium);
+      generate(result, marginLarge, attributes, Attributes.overwriteMarginLarge);
+      generate(result, marginExtraLarge, attributes, Attributes.overwriteMarginExtraLarge);
       return result.toArray(new BootstrapClass[result.size()]);
     }
 
-    private void generate(final List<BootstrapClass> result, final LayoutTokens tokens, Attributes attributes,
-        final Object overwrite) {
-      final BootstrapClass bootstrapClass;
+    private void generate(final List<BootstrapClass> result, final LayoutTokens tokens,
+        final Map<String, Object> attributes, final Attributes attribute) {
+      Object overwrite = attributes.get(attribute.name());
 
       if (overwrite != null) {
-        final LayoutTokens layoutTokens = LayoutTokens.parse((String) overwrite);
-        bootstrapClass = valueOf(layoutTokens.get(0), attributes);
+        final LayoutToken layoutToken = LayoutTokens.parseToken((String) overwrite);
+        final BootstrapClass bootstrapClass = valueOf(layoutToken, attribute);
+        result.add(bootstrapClass);
       } else if (tokens != null) {
         final LayoutToken layoutToken = tokens.get(index % tokens.getSize());
-        bootstrapClass = valueOf(layoutToken, attributes);
-      } else {
-        bootstrapClass = null;
+        final BootstrapClass bootstrapClass = valueOf(layoutToken, attribute);
+        result.add(bootstrapClass);
       }
-      if (bootstrapClass != null) {
+    }
+
+    private void generate(final List<BootstrapClass> result, final MarginTokens margins,
+        final Map<String, Object> attributes, final Attributes attribute) {
+      Object overwrite = attributes.get(attribute.name());
+
+      if (overwrite != null) {
+        final Margin margin = MarginTokens.parseToken((String) overwrite);
+        final BootstrapClass bootstrapClass = valueOf(margin, attribute);
+        result.add(bootstrapClass);
+      } else if (margins != null) {
+        final Margin margin = margins.get(index % margins.getSize());
+        final BootstrapClass bootstrapClass = valueOf(margin, attribute);
         result.add(bootstrapClass);
       }
     }
   }
 
   public static BootstrapClass valueOf(LayoutToken layoutToken, Attributes attributes) {
-    final String size;
-
-    switch (attributes) {
-      case extraLarge:
-        size = "_XL";
-        break;
-      case large:
-        size = "_LG";
-        break;
-      case medium:
-        size = "_MD";
-        break;
-      case small:
-        size = "_SM";
-        break;
-      case extraSmall:
-      default:
-        size = "";
-    }
+    final String size = getSizeSuffix(attributes);
 
     if (layoutToken instanceof RelativeLayoutToken) {
       return valueOf("COL" + size);
@@ -541,6 +568,52 @@ public enum BootstrapClass implements CssItem {
     }
   }
 
+  public static BootstrapClass valueOf(Margin margin, Attributes attribute) {
+    final String size = getSizeSuffix(attribute);
+
+    switch (margin) {
+      case left:
+        return valueOf("ML" + size + "_AUTO");
+      case right:
+        return valueOf("MR" + size + "_AUTO");
+      case both:
+        return valueOf("MX" + size + "_AUTO");
+      default:
+        return null;
+    }
+  }
+
+  private static String getSizeSuffix(Attributes attribute) {
+    switch (attribute) {
+      case extraLarge:
+      case marginExtraLarge:
+      case overwriteExtraLarge:
+      case overwriteMarginExtraLarge:
+        return "_XL";
+      case large:
+      case marginLarge:
+      case overwriteLarge:
+      case overwriteMarginLarge:
+        return "_LG";
+      case medium:
+      case marginMedium:
+      case overwriteMedium:
+      case overwriteMarginMedium:
+        return "_MD";
+      case small:
+      case marginSmall:
+      case overwriteSmall:
+      case overwriteMarginSmall:
+        return "_SM";
+      case extraSmall:
+      case marginExtraSmall:
+      case overwriteExtraSmall:
+      case overwriteMarginExtraSmall:
+      default:
+        return "";
+    }
+  }
+
   public static CssItem valueOf(AlignItems alignItems) {
     if (alignItems == null) {
       return null;
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/migration40.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/migration40.xhtml
index 53555f2..f1ed407 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/migration40.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/migration40.xhtml
@@ -35,7 +35,8 @@
       <li><tc:link link="" fragment="page:mainForm:css" label="CSS / Bootstrap"/></li>
       <li><tc:link link="" fragment="page:mainForm:theme" label="Theme building"/></li>
       <li><tc:link link="" fragment="page:mainForm:crlf" label="CRLF in textarea"/></li>
-      <li><tc:link link="" fragment="page:mainForm:resourceResolver" label="Removed class: MetaInfResourcesClasspathResourceResolver"/></li>
+      <li><tc:link link="" fragment="page:mainForm:resourceResolver"
+                   label="Removed class: MetaInfResourcesClasspathResourceResolver"/></li>
     </ul>
 
     <tc:section id="taglib" label="Tag Library">
@@ -49,31 +50,32 @@
           <code class="language-markup">&lt;tc:event></code>
           in Tobago 3 has three cases:
         </p>
-          <ol>
-              <li>
-                External link to an URL e. g. <code class="language-markup">link="http://www.apache.com"</code>
-                <p>
-                  Here is nothing to do.
-                </p>
-              </li>
-              <li>
-                Internal link to a resource  e. g. <code class="language-markup">link="image/alps.png"</code>
-                <p>
-                  Here you need to add the contextPath which might not be an empty string:
-                  <code class="language-markup">link="\#{request.contextPath}/image/alps.png"</code>.
-                  So, this is now the same like resouces used over other attributes.
-                </p>
-              </li>
-              <li>
-                Internal link to a viewId e. g. <code class="language-markup">link="/intro.xhtml"</code>
-                <p>
-                  In this case you need to use the new attribute <code class="language-markup">outcome="/intro.xhtml"</code>.
-                  Please use only full pathes here!
-                  This this, the GET parameter will be respected.
-                  This is needed e. g. for the windowId of <tc:link label="DeltaSpike" link="https://deltaspike.apache.org/"/>.
-                </p>
-              </li>
-          </ol>
+        <ol>
+          <li>
+            External link to an URL e. g. <code class="language-markup">link="http://www.apache.com"</code>
+            <p>
+              Here is nothing to do.
+            </p>
+          </li>
+          <li>
+            Internal link to a resource e. g. <code class="language-markup">link="image/alps.png"</code>
+            <p>
+              Here you need to add the contextPath which might not be an empty string:
+              <code class="language-markup">link="\#{request.contextPath}/image/alps.png"</code>.
+              So, this is now the same like resouces used over other attributes.
+            </p>
+          </li>
+          <li>
+            Internal link to a viewId e. g. <code class="language-markup">link="/intro.xhtml"</code>
+            <p>
+              In this case you need to use the new attribute <code class="language-markup">outcome="/intro.xhtml"</code>.
+              Please use only full pathes here!
+              This this, the GET parameter will be respected.
+              This is needed e. g. for the windowId of <tc:link label="DeltaSpike"
+                                                                link="https://deltaspike.apache.org/"/>.
+            </p>
+          </li>
+        </ol>
       </tc:section>
 
       <tc:section label="&lt;tc:bar&gt;">
@@ -100,13 +102,23 @@
         <p>For more information have a look at
           <tc:link label="tc:bar" outcome="/content/20-component/050-container/60-bar/bar.xhtml"/></p>
       </tc:section>
+      <tc:section label="&lt;tc:segmentLayoutConstraint>">
+        <p>The offset concept changed in Bootstrap Beta.
+          The attributes <code>offsetExtraSmall</code>, <code>offsetSmall</code>, <code>offsetMedium</code> and
+          <code>offsetLarge</code> are <b>removed</b>
+          from <code class="language-markup">&lt;tc:segmentLayoutConstraint/></code>.</p>
+        <p>Instead use the new
+          <tc:link label="margin concept"
+                   link="/content/30-concept/16-layout/30-segment/segment-layout.xhtml#page:mainForm:marginConcept"/>.
+        </p>
+      </tc:section>
     </tc:section>
 
     <tc:section id="css" label="CSS / Bootstrap">
       <p>
         The included Bootstrap CSS library has been updated from
         <tc:link link="http://blog.getbootstrap.com/2016/10/19/bootstrap-4-alpha-5/" label="v4.0.0-alpha.5"/> to
-        <tc:link link="http://blog.getbootstrap.com/2017/01/06/bootstrap-4-alpha-6/" label="v4.0.0-alpha.6"/>.
+        <tc:link link="http://blog.getbootstrap.com/2017/08/10/bootstrap-4-beta/" label="v4.0.0-beta"/>.
         Thought some changes need to be made, if you use Bootstrap classes directly.
       </p>
       <p>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml
index 26e12e7..6a4a473 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml
@@ -79,7 +79,7 @@
 
   <tc:section label="Screen Size">
     <p>For the different kinds of screen sizes, the segment layout has five attributes:
-      <code>extraLarge</code>, <code>large</code>, <code>medium</code>, <code>small</code> and <code>extraSmall</code>.
+      <code>extraSmall</code>, <code>small</code>, <code>medium</code>, <code>large</code> and <code>extraLarge</code>.
       The first three should be used for desktops. The last two should be used for tablets and phones.
       Notice, that only the browser size matters. So a small browser window on a big screen also reacts with
       <code>small</code> and <code>extraSmall</code>.</p>
@@ -105,25 +105,45 @@
     </tc:segmentLayout>
   </tc:section>
 
+  <tc:section id="marginConcept" label="Margin">
+    <p>A margin can be set for the different proportions with the attributes
+      <code>marginExtraSmall</code>, <code>marginSmall</code>, <code>marginMedium</code>, <code>marginLarge</code> and
+      <code>marginExtraLarge</code>.</p>
+    <p>Possible values are <code>none</code>, <code>left</code>, <code>right</code> and <code>both</code>.</p>
+
+    <pre><code class="language-markup">&lt;tc:segmentLayout extraSmall="5;3"
+      marginExtraSmall="none;both;left;both">
+    ...</code></pre>
+    <tc:segmentLayout extraSmall="5;3" marginExtraSmall="none;both;left;both">
+      <tc:in value="none"/>
+      <tc:in value="both"/>
+      <tc:in value="none"/>
+      <tc:in value="both"/>
+      <tc:in value="none"/>
+      <tc:in value="both"/>
+    </tc:segmentLayout>
+  </tc:section>
+
   <tc:section label="Overwrite default layout">
-    <p>The default layout can be overwritten by the
+    <p>The default layout and margins can be overwritten by the
       <code class="language-markup">&lt;tc:segmentLayoutConstraint/></code> tag.
-      Possible attributes are <code>extraSmall</code>, <code>small</code>,<code>medium</code> and
-      <code>large</code>.</p>
-    <p>In the following example the medium default layout of the third input field is overwritter with '3'.</p>
-    <pre><code class="language-markup">&lt;tc:segmentLayout medium="4;8">
-  &lt;tc:in/>
-  &lt;tc:in/>
-  &lt;tc:in>
-    &lt;tc:segmentLayoutConstraint medium="3"/>
+      Possible attributes are <code>extraSmall</code>, <code>small</code>, <code>medium</code>, <code>large</code> and
+      <code>extraLarge</code> for the layout.<br/>
+      And: <code>marginExtraSmall</code>, <code>marginSmall</code>, <code>marginMedium</code>, <code>marginLarge</code>,
+      <code>marginExtraLarge</code> for the margins.</p>
+    <pre><code class="language-markup">&lt;tc:segmentLayout extraSmall="4;8">
+  &lt;tc:in value="4"/>
+  &lt;tc:in value="8"/>
+  &lt;tc:in value="3 - both">
+    &lt;tc:segmentLayoutConstraint extraSmall="3" marginExtraSmall="both"/>
   &lt;/tc:in>
-  &lt;tc:in/>
+  &lt;tc:in value="8"/>
 &lt;/tc:segmentLayout></code></pre>
-    <tc:segmentLayout medium="4;8">
+    <tc:segmentLayout extraSmall="4;8">
       <tc:in value="4"/>
       <tc:in value="8"/>
-      <tc:in value="3">
-        <tc:segmentLayoutConstraint medium="3"/>
+      <tc:in value="3 - both">
+        <tc:segmentLayoutConstraint extraSmall="3" marginExtraSmall="both"/>
       </tc:in>
       <tc:in value="8"/>
     </tc:segmentLayout>

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